Get rid of exceptions in llvmc.
[oota-llvm.git] / 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
18 #include "llvm/Support/raw_ostream.h"
19 #include "llvm/Support/SystemUtils.h"
20 #include "llvm/System/Program.h"
21 #include "llvm/System/TimeValue.h"
22
23 #include <stdexcept>
24 #include <string>
25
26 using namespace llvm;
27 using namespace llvmc;
28
29 namespace llvmc {
30
31 extern int Main(int argc, char** argv);
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,
57                       const StrVector& args) {
58     sys::Path prog = sys::Program::FindProgramByName(name);
59
60     if (prog.isEmpty()) {
61       prog = FindExecutable(name, ProgramName, (void *)(intptr_t)&Main);
62       if (prog.isEmpty()) {
63         PrintError("Can't find program '" + name + "'");
64         return -1;
65       }
66     }
67     if (!prog.canExecute()) {
68       PrintError("Program '" + name + "' is not executable.");
69       return -1;
70     }
71
72     // Build the command line vector and the redirects array.
73     const sys::Path* redirects[3] = {0,0,0};
74     sys::Path stdout_redirect;
75
76     std::vector<const char*> argv;
77     argv.reserve((args.size()+2));
78     argv.push_back(name.c_str());
79
80     for (StrVector::const_iterator B = args.begin(), E = args.end();
81          B!=E; ++B) {
82       if (*B == ">") {
83         ++B;
84         stdout_redirect.set(*B);
85         redirects[1] = &stdout_redirect;
86       }
87       else {
88         argv.push_back((*B).c_str());
89       }
90     }
91     argv.push_back(0);  // null terminate list.
92
93     // Invoke the program.
94     int ret = sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]);
95
96     if (IsSegmentationFault(ret)) {
97       errs() << "Segmentation fault: ";
98       PrintCommand(name, args);
99     }
100
101     return ret;
102   }
103 }
104
105 namespace llvmc {
106   void AppendToGlobalTimeLog (const std::string& cmd, double time);
107 }
108
109 int llvmc::Action::Execute () const {
110   if (DryRun || VerboseMode)
111     PrintCommand(Command_, Args_);
112
113   if (!DryRun) {
114     if (Time) {
115       sys::TimeValue now = sys::TimeValue::now();
116       int ret = ExecuteProgram(Command_, Args_);
117       sys::TimeValue now2 = sys::TimeValue::now();
118       now2 -= now;
119       double elapsed = now2.seconds()  + now2.microseconds()  / 1000000.0;
120       AppendToGlobalTimeLog(Command_, elapsed);
121
122       return ret;
123     }
124     else {
125       return ExecuteProgram(Command_, Args_);
126     }
127   }
128
129   return 0;
130 }