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