b5e507dfc3a37e70d7d8da8bf86a853cd21caa36
[oota-llvm.git] / lib / CompilerDriver / Main.cpp
1 //===--- Main.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 //  llvmc::Main function - driver entry point.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/CompilerDriver/BuiltinOptions.h"
15 #include "llvm/CompilerDriver/CompilationGraph.h"
16 #include "llvm/CompilerDriver/Error.h"
17 #include "llvm/CompilerDriver/Plugin.h"
18
19 #include "llvm/Support/raw_ostream.h"
20 #include "llvm/System/Path.h"
21
22 #include <sstream>
23 #include <stdexcept>
24 #include <string>
25
26 namespace cl = llvm::cl;
27 namespace sys = llvm::sys;
28 using namespace llvmc;
29
30 namespace {
31
32   std::stringstream* GlobalTimeLog;
33
34   sys::Path getTempDir() {
35     sys::Path tempDir;
36
37     // The --temp-dir option.
38     if (!TempDirname.empty()) {
39       tempDir = TempDirname;
40     }
41     // GCC 4.5-style -save-temps handling.
42     else if (SaveTemps == SaveTempsEnum::Unset) {
43       tempDir = sys::Path::GetTemporaryDirectory();
44       return tempDir;
45     }
46     else if (SaveTemps == SaveTempsEnum::Obj && !OutputFilename.empty()) {
47       tempDir = OutputFilename;
48       tempDir = tempDir.getDirname();
49     }
50     else {
51       // SaveTemps == Cwd --> use current dir (leave tempDir empty).
52       return tempDir;
53     }
54
55     if (!tempDir.exists()) {
56       std::string ErrMsg;
57       if (tempDir.createDirectoryOnDisk(true, &ErrMsg))
58         throw std::runtime_error(ErrMsg);
59     }
60
61     return tempDir;
62   }
63
64   /// BuildTargets - A small wrapper for CompilationGraph::Build.
65   int BuildTargets(CompilationGraph& graph, const LanguageMap& langMap) {
66     int ret;
67     const sys::Path& tempDir = getTempDir();
68     bool toDelete = (SaveTemps == SaveTempsEnum::Unset);
69
70     try {
71       ret = graph.Build(tempDir, langMap);
72     }
73     catch(...) {
74       if (toDelete)
75         tempDir.eraseFromDisk(true);
76       throw;
77     }
78
79     if (toDelete)
80       tempDir.eraseFromDisk(true);
81     return ret;
82   }
83 }
84
85 namespace llvmc {
86
87 // Used to implement -time option. External linkage is intentional.
88 void AppendToGlobalTimeLog(const std::string& cmd, double time) {
89   *GlobalTimeLog << "# " << cmd << ' ' << time << '\n';
90 }
91
92 // Sometimes plugins want to condition on the value in argv[0].
93 const char* ProgramName;
94
95 int Main(int argc, char** argv) {
96   try {
97     LanguageMap langMap;
98     CompilationGraph graph;
99
100     ProgramName = argv[0];
101
102     cl::ParseCommandLineOptions
103       (argc, argv, "LLVM Compiler Driver (Work In Progress)",
104        /* ReadResponseFiles = */ false);
105
106     PluginLoader Plugins;
107     Plugins.RunInitialization(langMap, graph);
108
109     if (CheckGraph) {
110       int ret = graph.Check();
111       if (!ret)
112         llvm::errs() << "check-graph: no errors found.\n";
113
114       return ret;
115     }
116
117     if (ViewGraph) {
118       graph.viewGraph();
119       if (!WriteGraph)
120         return 0;
121     }
122
123     if (WriteGraph) {
124       graph.writeGraph(OutputFilename.empty()
125                        ? std::string("compilation-graph.dot")
126                        : OutputFilename);
127       return 0;
128     }
129
130     if (Time) {
131       GlobalTimeLog = new std::stringstream;
132       GlobalTimeLog->precision(2);
133     }
134
135     int ret = BuildTargets(graph, langMap);
136
137     if (Time) {
138       llvm::errs() << GlobalTimeLog->str();
139       delete GlobalTimeLog;
140     }
141
142     return ret;
143   }
144   catch(llvmc::error_code& ec) {
145     return ec.code();
146   }
147   catch(const std::exception& ex) {
148     llvm::errs() << argv[0] << ": " << ex.what() << '\n';
149   }
150   catch(...) {
151     llvm::errs() << argv[0] << ": unknown error!\n";
152   }
153   return 1;
154 }
155
156 } // end namespace llvmc