• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/AutoGenerated.h"
15 #include "llvm/CompilerDriver/BuiltinOptions.h"
16 #include "llvm/CompilerDriver/CompilationGraph.h"
17 #include "llvm/CompilerDriver/Error.h"
18 
19 #include "llvm/Support/FileSystem.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include "llvm/Support/Path.h"
22 
23 #include <sstream>
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   /// GetTempDir - Get the temporary directory location. Returns non-zero value
35   /// on error.
GetTempDir(sys::Path & tempDir)36   int GetTempDir(sys::Path& tempDir) {
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 0;
45     }
46     else if (SaveTemps == SaveTempsEnum::Obj && !OutputFilename.empty()) {
47       tempDir = sys::path::parent_path(OutputFilename);
48     }
49     else {
50       // SaveTemps == Cwd --> use current dir (leave tempDir empty).
51       return 0;
52     }
53 
54     bool Exists;
55     if (llvm::sys::fs::exists(tempDir.str(), Exists) || !Exists) {
56       std::string ErrMsg;
57       if (tempDir.createDirectoryOnDisk(true, &ErrMsg)) {
58         PrintError(ErrMsg);
59         return 1;
60       }
61     }
62 
63     return 0;
64   }
65 
66   /// BuildTargets - A small wrapper for CompilationGraph::Build. Returns
67   /// non-zero value in case of error.
BuildTargets(CompilationGraph & graph,const LanguageMap & langMap)68   int BuildTargets(CompilationGraph& graph, const LanguageMap& langMap) {
69     int ret;
70     sys::Path tempDir;
71     bool toDelete = (SaveTemps == SaveTempsEnum::Unset);
72 
73     if (int ret = GetTempDir(tempDir))
74       return ret;
75 
76     ret = graph.Build(tempDir, langMap);
77 
78     if (toDelete)
79       tempDir.eraseFromDisk(true);
80 
81     return ret;
82   }
83 }
84 
85 namespace llvmc {
86 
87 // Used to implement -time option. External linkage is intentional.
AppendToGlobalTimeLog(const std::string & cmd,double time)88 void AppendToGlobalTimeLog(const std::string& cmd, double time) {
89   *GlobalTimeLog << "# " << cmd << ' ' << time << '\n';
90 }
91 
92 // Sometimes user code wants to access the argv[0] value.
93 const char* ProgramName;
94 
Main(int argc,char ** argv)95 int Main(int argc, char** argv) {
96   int ret = 0;
97   LanguageMap langMap;
98   CompilationGraph graph;
99 
100   ProgramName = argv[0];
101 
102   cl::ParseCommandLineOptions
103     (argc, argv,
104      /* Overview = */ "LLVM Compiler Driver (Work In Progress)",
105      /* ReadResponseFiles = */ false);
106 
107   if (int ret = autogenerated::RunInitialization(langMap, graph))
108     return ret;
109 
110   if (CheckGraph) {
111     ret = graph.Check();
112     if (!ret)
113       llvm::errs() << "check-graph: no errors found.\n";
114 
115     return ret;
116   }
117 
118   if (ViewGraph) {
119     graph.viewGraph();
120     if (!WriteGraph)
121       return 0;
122   }
123 
124   if (WriteGraph) {
125     const std::string& Out = (OutputFilename.empty()
126                               ? std::string("compilation-graph.dot")
127                               : OutputFilename);
128     return graph.writeGraph(Out);
129   }
130 
131   if (Time) {
132     GlobalTimeLog = new std::stringstream;
133     GlobalTimeLog->precision(2);
134   }
135 
136   ret = BuildTargets(graph, langMap);
137 
138   if (Time) {
139     llvm::errs() << GlobalTimeLog->str();
140     delete GlobalTimeLog;
141   }
142 
143   return ret;
144 }
145 
146 } // end namespace llvmc
147