Remove some duplication.
[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 <stdexcept>
23 #include <string>
24
25 namespace cl = llvm::cl;
26 namespace sys = llvm::sys;
27 using namespace llvmc;
28
29 namespace {
30
31   sys::Path getTempDir() {
32     sys::Path tempDir;
33
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 tempDir;
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 tempDir;
50     }
51
52     if (!tempDir.exists()) {
53       std::string ErrMsg;
54       if (tempDir.createDirectoryOnDisk(true, &ErrMsg))
55         throw std::runtime_error(ErrMsg);
56     }
57
58     return tempDir;
59   }
60
61   /// BuildTargets - A small wrapper for CompilationGraph::Build.
62   int BuildTargets(CompilationGraph& graph, const LanguageMap& langMap) {
63     int ret;
64     const sys::Path& tempDir = getTempDir();
65     bool toDelete =
66       (SaveTemps == SaveTempsEnum::Unset && TempDirname.empty());
67
68     try {
69       ret = graph.Build(tempDir, langMap);
70     }
71     catch(...) {
72       if (toDelete)
73         tempDir.eraseFromDisk(true);
74       throw;
75     }
76
77     if (toDelete)
78       tempDir.eraseFromDisk(true);
79     return ret;
80   }
81 }
82
83 namespace llvmc {
84
85 // Sometimes plugins want to condition on the value in argv[0].
86 const char* ProgramName;
87
88 int Main(int argc, char** argv) {
89   try {
90     LanguageMap langMap;
91     CompilationGraph graph;
92
93     ProgramName = argv[0];
94
95     cl::ParseCommandLineOptions
96       (argc, argv, "LLVM Compiler Driver (Work In Progress)", true);
97
98     PluginLoader Plugins;
99     Plugins.PopulateLanguageMap(langMap);
100     Plugins.PopulateCompilationGraph(graph);
101
102     if (CheckGraph) {
103       int ret = graph.Check();
104       if (!ret)
105         llvm::errs() << "check-graph: no errors found.\n";
106
107       return ret;
108     }
109
110     if (ViewGraph) {
111       graph.viewGraph();
112       if (!WriteGraph)
113         return 0;
114     }
115
116     if (WriteGraph) {
117       graph.writeGraph(OutputFilename.empty()
118                        ? std::string("compilation-graph.dot")
119                        : OutputFilename);
120       return 0;
121     }
122
123     if (InputFilenames.empty()) {
124       throw std::runtime_error("no input files");
125     }
126
127     return BuildTargets(graph, langMap);
128   }
129   catch(llvmc::error_code& ec) {
130     return ec.code();
131   }
132   catch(const std::exception& ex) {
133     llvm::errs() << argv[0] << ": " << ex.what() << '\n';
134   }
135   catch(...) {
136     llvm::errs() << argv[0] << ": unknown error!\n";
137   }
138   return 1;
139 }
140
141 } // end namespace llvmc