MC: Factor out MCAssembler::EvaluateFixup, and simplify.
[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     return sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]);
71   }
72
73   void print_string (const std::string& str) {
74     errs() << str << ' ';
75   }
76 }
77
78 namespace llvmc {
79   void AppendToGlobalTimeLog(const std::string& cmd, double time);
80 }
81
82 int llvmc::Action::Execute() const {
83   if (DryRun || VerboseMode) {
84     errs() << Command_ << " ";
85     std::for_each(Args_.begin(), Args_.end(), print_string);
86     errs() << '\n';
87   }
88   if (!DryRun) {
89     if (Time) {
90       sys::TimeValue now = sys::TimeValue::now();
91       int ret = ExecuteProgram(Command_, Args_);
92       sys::TimeValue now2 = sys::TimeValue::now();
93       now2 -= now;
94       double elapsed = now2.seconds()  + now2.microseconds()  / 1000000.0;
95       AppendToGlobalTimeLog(Command_, elapsed);
96
97       return ret;
98     }
99     else {
100       return ExecuteProgram(Command_, Args_);
101     }
102   }
103
104   return 0;
105 }