8c63a4da53ef08a8e8b2e478f40d6e681440bcaa
[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
17 #include "llvm/Support/raw_ostream.h"
18 #include "llvm/Support/SystemUtils.h"
19 #include "llvm/System/Program.h"
20 #include "llvm/System/TimeValue.h"
21
22 #include <stdexcept>
23 #include <string>
24
25 using namespace llvm;
26 using namespace llvmc;
27
28 namespace llvmc {
29
30 extern int Main(int argc, char** argv);
31 extern const char* ProgramName;
32
33 }
34
35 namespace {
36   int ExecuteProgram(const std::string& name,
37                      const StrVector& args) {
38     sys::Path prog = sys::Program::FindProgramByName(name);
39
40     if (prog.isEmpty()) {
41       prog = FindExecutable(name, ProgramName, (void *)(intptr_t)&Main);
42       if (prog.isEmpty())
43         throw std::runtime_error("Can't find program '" + name + "'");
44     }
45     if (!prog.canExecute())
46       throw std::runtime_error("Program '" + name + "' is not executable.");
47
48     // Build the command line vector and the redirects array.
49     const sys::Path* redirects[3] = {0,0,0};
50     sys::Path stdout_redirect;
51
52     std::vector<const char*> argv;
53     argv.reserve((args.size()+2));
54     argv.push_back(name.c_str());
55
56     for (StrVector::const_iterator B = args.begin(), E = args.end();
57          B!=E; ++B) {
58       if (*B == ">") {
59         ++B;
60         stdout_redirect.set(*B);
61         redirects[1] = &stdout_redirect;
62       }
63       else {
64         argv.push_back((*B).c_str());
65       }
66     }
67     argv.push_back(0);  // null terminate list.
68
69     // Invoke the program.
70     int ret = sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]);
71
72     if (ret < 0) {
73       const char** B = &argv[0];
74
75       errs() << "Segmentation fault:";
76       while (*B)
77         errs() << ' ' << *(B++);
78       errs() << '\n';
79
80       return 1;
81     }
82
83     return ret;
84   }
85
86   void print_string (const std::string& str) {
87     errs() << str << ' ';
88   }
89 }
90
91 namespace llvmc {
92   void AppendToGlobalTimeLog(const std::string& cmd, double time);
93 }
94
95 int llvmc::Action::Execute() const {
96   if (DryRun || VerboseMode) {
97     errs() << Command_ << " ";
98     std::for_each(Args_.begin(), Args_.end(), print_string);
99     errs() << '\n';
100   }
101   if (!DryRun) {
102     if (Time) {
103       sys::TimeValue now = sys::TimeValue::now();
104       int ret = ExecuteProgram(Command_, Args_);
105       sys::TimeValue now2 = sys::TimeValue::now();
106       now2 -= now;
107       double elapsed = now2.seconds()  + now2.microseconds()  / 1000000.0;
108       AppendToGlobalTimeLog(Command_, elapsed);
109
110       return ret;
111     }
112     else {
113       return ExecuteProgram(Command_, Args_);
114     }
115   }
116
117   return 0;
118 }