f4cacb38f183ef04c028f4a7c6bec698a137dc06
[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 /////////////////////////////////////////////
35     std::string p = "tmp-objs";
36     tempDir = sys::Path(p);
37       if (!tempDir.exists()) {
38         std::string ErrMsg;
39         if (tempDir.createDirectoryOnDisk(true, &ErrMsg))
40           throw std::runtime_error(ErrMsg);
41       }
42     return tempDir;
43 /////////////////////////////////////////////
44
45     // GCC 4.5-style -save-temps handling.
46     if (SaveTemps == SaveTempsEnum::Unset) {
47       tempDir = sys::Path::GetTemporaryDirectory();
48     }
49     else if (SaveTemps == SaveTempsEnum::Obj && !OutputFilename.empty()) {
50       tempDir = OutputFilename;
51       tempDir = tempDir.getDirname();
52
53       if (!tempDir.exists()) {
54         std::string ErrMsg;
55         if (tempDir.createDirectoryOnDisk(true, &ErrMsg))
56           throw std::runtime_error(ErrMsg);
57       }
58     }
59     // else if (SaveTemps == Cwd) -> use current dir (leave tempDir empty)
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
69     try {
70       ret = graph.Build(tempDir, langMap);
71     }
72     catch(...) {
73       if (SaveTemps == SaveTempsEnum::Unset)
74         tempDir.eraseFromDisk(true);
75       throw;
76     }
77
78     if (SaveTemps == SaveTempsEnum::Unset)
79       tempDir.eraseFromDisk(true);
80     return ret;
81   }
82 }
83
84 namespace llvmc {
85
86 // Sometimes plugins want to condition on the value in argv[0].
87 const char* ProgramName;
88
89 int Main(int argc, char** argv) {
90   try {
91     LanguageMap langMap;
92     CompilationGraph graph;
93
94     ProgramName = argv[0];
95
96     cl::ParseCommandLineOptions
97       (argc, argv, "LLVM Compiler Driver (Work In Progress)", true);
98
99     PluginLoader Plugins;
100     Plugins.PopulateLanguageMap(langMap);
101     Plugins.PopulateCompilationGraph(graph);
102
103     if (CheckGraph) {
104       int ret = graph.Check();
105       if (!ret)
106         llvm::errs() << "check-graph: no errors found.\n";
107
108       return ret;
109     }
110
111     if (ViewGraph) {
112       graph.viewGraph();
113       if (!WriteGraph)
114         return 0;
115     }
116
117     if (WriteGraph) {
118       graph.writeGraph(OutputFilename.empty()
119                        ? std::string("compilation-graph.dot")
120                        : OutputFilename);
121       return 0;
122     }
123
124     if (InputFilenames.empty()) {
125       throw std::runtime_error("no input files");
126     }
127
128     return BuildTargets(graph, langMap);
129   }
130   catch(llvmc::error_code& ec) {
131     return ec.code();
132   }
133   catch(const std::exception& ex) {
134     llvm::errs() << argv[0] << ": " << ex.what() << '\n';
135   }
136   catch(...) {
137     llvm::errs() << argv[0] << ": unknown error!\n";
138   }
139   return 1;
140 }
141
142 } // end namespace llvmc