]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/lib/CompilerDriver/Action.cpp
Copy head to stable/9 as part of 9.0-RELEASE release cycle.
[FreeBSD/stable/9.git] / contrib / llvm / lib / CompilerDriver / Action.cpp
1 //===--- Action.cpp - The LLVM Compiler Driver ------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open
6 // Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  Action class - implementation and auxiliary functions.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/CompilerDriver/Action.h"
15 #include "llvm/CompilerDriver/BuiltinOptions.h"
16 #include "llvm/CompilerDriver/Error.h"
17 #include "llvm/CompilerDriver/Main.h"
18
19 #include "llvm/Support/raw_ostream.h"
20 #include "llvm/Support/SystemUtils.h"
21 #include "llvm/Support/Program.h"
22 #include "llvm/Support/TimeValue.h"
23
24 #include <stdexcept>
25 #include <string>
26
27 using namespace llvm;
28 using namespace llvmc;
29
30 namespace llvmc {
31
32 extern const char* ProgramName;
33
34 }
35
36 namespace {
37
38   void PrintString (const std::string& str) {
39     errs() << str << ' ';
40   }
41
42   void PrintCommand (const std::string& Cmd, const StrVector& Args) {
43     errs() << Cmd << ' ';
44     std::for_each(Args.begin(), Args.end(), &PrintString);
45     errs() << '\n';
46   }
47
48   bool IsSegmentationFault (int returnCode) {
49 #ifdef LLVM_ON_WIN32
50     return (returnCode >= 0xc0000000UL)
51 #else
52     return (returnCode < 0);
53 #endif
54   }
55
56   int ExecuteProgram (const std::string& name, const StrVector& args) {
57     sys::Path prog(name);
58
59     if (sys::path::is_relative(prog.str())) {
60       prog = PrependMainExecutablePath(name, ProgramName,
61                                        (void *)(intptr_t)&Main);
62
63       if (!prog.canExecute()) {
64         prog = sys::Program::FindProgramByName(name);
65         if (prog.isEmpty()) {
66           PrintError("Can't find program '" + name + "'");
67           return -1;
68         }
69       }
70     }
71     if (!prog.canExecute()) {
72       PrintError("Program '" + name + "' is not executable.");
73       return -1;
74     }
75
76     // Build the command line vector and the redirects array.
77     const sys::Path* redirects[3] = {0,0,0};
78     sys::Path stdout_redirect;
79
80     std::vector<const char*> argv;
81     argv.reserve((args.size()+2));
82     argv.push_back(name.c_str());
83
84     for (StrVector::const_iterator B = args.begin(), E = args.end();
85          B!=E; ++B) {
86       if (*B == ">") {
87         ++B;
88         stdout_redirect.set(*B);
89         redirects[1] = &stdout_redirect;
90       }
91       else {
92         argv.push_back((*B).c_str());
93       }
94     }
95     argv.push_back(0);  // null terminate list.
96
97     // Invoke the program.
98     int ret = sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]);
99
100     if (IsSegmentationFault(ret)) {
101       errs() << "Segmentation fault: ";
102       PrintCommand(name, args);
103     }
104
105     return ret;
106   }
107 }
108
109 namespace llvmc {
110   void AppendToGlobalTimeLog (const std::string& cmd, double time);
111 }
112
113 int llvmc::Action::Execute () const {
114   if (DryRun || VerboseMode)
115     PrintCommand(Command_, Args_);
116
117   if (!DryRun) {
118     if (Time) {
119       sys::TimeValue now = sys::TimeValue::now();
120       int ret = ExecuteProgram(Command_, Args_);
121       sys::TimeValue now2 = sys::TimeValue::now();
122       now2 -= now;
123       double elapsed = now2.seconds()  + now2.microseconds()  / 1000000.0;
124       AppendToGlobalTimeLog(Command_, elapsed);
125
126       return ret;
127     }
128     else {
129       return ExecuteProgram(Command_, Args_);
130     }
131   }
132
133   return 0;
134 }