1 //===--- llvmc.cpp - The LLVM Compiler Driver -------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by Reid Spencer and is distributed under the
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This tool provides a single point of access to the LLVM compilation tools.
11 // It has many options. To discover the options supported please refer to the
12 // tools' manual page (docs/CommandGuide/html/llvmc.html) or run the tool with
15 //===----------------------------------------------------------------------===//
17 #include "CompilerDriver.h"
18 #include "Configuration.h"
19 #include "llvm/Pass.h"
20 #include "llvm/Support/CommandLine.h"
21 #include "llvm/Support/ManagedStatic.h"
22 #include "llvm/System/Signals.h"
26 //===----------------------------------------------------------------------===//
28 //===----------------------------------------------------------------------===//
29 static cl::opt
<CompilerDriver::Phases
> FinalPhase(cl::Optional
,
30 cl::desc("Choose final phase of compilation:"),
31 cl::init(CompilerDriver::LINKING
),
33 clEnumValN(CompilerDriver::PREPROCESSING
,"E",
34 "Stop compilation after pre-processing phase"),
35 clEnumValN(CompilerDriver::TRANSLATION
, "t",
36 "Stop compilation after translation phase"),
37 clEnumValN(CompilerDriver::OPTIMIZATION
,"c",
38 "Stop compilation after optimization phase"),
39 clEnumValN(CompilerDriver::ASSEMBLY
,"S",
40 "Stop compilation after assembly phase"),
45 //===----------------------------------------------------------------------===//
46 //=== OPTIMIZATION OPTIONS
47 //===----------------------------------------------------------------------===//
48 static cl::opt
<CompilerDriver::OptimizationLevels
> OptLevel(cl::ZeroOrMore
,
49 cl::desc("Choose level of optimization to apply:"),
50 cl::init(CompilerDriver::OPT_FAST_COMPILE
),
52 clEnumValN(CompilerDriver::OPT_FAST_COMPILE
,"O0",
53 "An alias for the -O1 option"),
54 clEnumValN(CompilerDriver::OPT_FAST_COMPILE
,"O1",
55 "Optimize for compilation speed, not execution speed"),
56 clEnumValN(CompilerDriver::OPT_SIMPLE
,"O2",
57 "Perform simple translation time optimizations"),
58 clEnumValN(CompilerDriver::OPT_AGGRESSIVE
,"O3",
59 "Perform aggressive translation time optimizations"),
60 clEnumValN(CompilerDriver::OPT_LINK_TIME
,"O4",
61 "Perform link time optimizations"),
62 clEnumValN(CompilerDriver::OPT_AGGRESSIVE_LINK_TIME
,"O5",
63 "Perform aggressive link time optimizations"),
68 //===----------------------------------------------------------------------===//
70 //===----------------------------------------------------------------------===//
72 static cl::list
<std::string
> PreprocessorToolOpts("Tpre", cl::ZeroOrMore
,
73 cl::desc("Pass specific options to the pre-processor"),
74 cl::value_desc("option"));
76 static cl::alias
PreprocessorToolOptsAlias("Wp,", cl::ZeroOrMore
,
77 cl::desc("Alias for -Tpre"), cl::aliasopt(PreprocessorToolOpts
));
79 static cl::list
<std::string
> TranslatorToolOpts("Ttrn", cl::ZeroOrMore
,
80 cl::desc("Pass specific options to the assembler"),
81 cl::value_desc("option"));
83 static cl::list
<std::string
> AssemblerToolOpts("Tasm", cl::ZeroOrMore
,
84 cl::desc("Pass specific options to the assembler"),
85 cl::value_desc("option"));
87 static cl::alias
AssemblerToolOptsAlias("Wa,", cl::ZeroOrMore
,
88 cl::desc("Alias for -Tasm"), cl::aliasopt(AssemblerToolOpts
));
90 static cl::list
<std::string
> OptimizerToolOpts("Topt", cl::ZeroOrMore
,
91 cl::desc("Pass specific options to the optimizer"),
92 cl::value_desc("option"));
94 static cl::list
<std::string
> LinkerToolOpts("Tlnk", cl::ZeroOrMore
,
95 cl::desc("Pass specific options to the linker"),
96 cl::value_desc("option"));
98 static cl::alias
LinkerToolOptsAlias("Wl,", cl::ZeroOrMore
,
99 cl::desc("Alias for -Tlnk"), cl::aliasopt(LinkerToolOpts
));
101 static cl::list
<std::string
> fOpts("f", cl::ZeroOrMore
, cl::Prefix
,
102 cl::desc("Pass through -f options to compiler tools"),
103 cl::value_desc("option"));
105 static cl::list
<std::string
> MOpts("M", cl::ZeroOrMore
, cl::Prefix
,
106 cl::desc("Pass through -M options to compiler tools"),
107 cl::value_desc("option"));
109 static cl::list
<std::string
> WOpts("W", cl::ZeroOrMore
, cl::Prefix
,
110 cl::desc("Pass through -W options to compiler tools"),
111 cl::value_desc("option"));
113 static cl::list
<std::string
> BOpt("B", cl::ZeroOrMore
, cl::Prefix
,
114 cl::desc("Specify path to find llvmc sub-tools"),
115 cl::value_desc("dir"));
117 //===----------------------------------------------------------------------===//
119 //===----------------------------------------------------------------------===//
121 static cl::list
<std::string
> LibPaths("L", cl::Prefix
,
122 cl::desc("Specify a library search path"), cl::value_desc("dir"));
124 static cl::list
<std::string
> Libraries("l", cl::Prefix
,
125 cl::desc("Specify base name of libraries to link to"), cl::value_desc("lib"));
127 static cl::list
<std::string
> Includes("I", cl::Prefix
,
128 cl::desc("Specify location to search for included source"),
129 cl::value_desc("dir"));
131 static cl::list
<std::string
> Defines("D", cl::Prefix
,
132 cl::desc("Specify a pre-processor symbol to define"),
133 cl::value_desc("symbol"));
135 //===----------------------------------------------------------------------===//
137 //===----------------------------------------------------------------------===//
139 static cl::opt
<std::string
> OutputFilename("o",
140 cl::desc("Override output filename"), cl::value_desc("file"));
142 static cl::opt
<std::string
> OutputMachine("m", cl::Prefix
,
143 cl::desc("Specify a target machine"), cl::value_desc("machine"));
145 static cl::opt
<bool> Native("native", cl::init(false),
146 cl::desc("Generative native code instead of bitcode"));
148 static cl::opt
<bool> DebugOutput("g", cl::init(false),
149 cl::desc("Generate objects that include debug symbols"));
151 static cl::opt
<bool> StripOutput("strip", cl::init(false),
152 cl::desc("Strip all symbols from linked output file"));
154 static cl::opt
<std::string
> PrintFileName("print-fname", cl::Optional
,
155 cl::value_desc("file"),
156 cl::desc("Print the full path for the option's value"));
158 //===----------------------------------------------------------------------===//
159 //=== INFORMATION OPTIONS
160 //===----------------------------------------------------------------------===//
162 static cl::opt
<bool> DryRun("dry-run", cl::Optional
, cl::init(false),
163 cl::desc("Do everything but perform the compilation actions"));
165 static cl::alias
DryRunAlias("y", cl::Optional
,
166 cl::desc("Alias for -dry-run"), cl::aliasopt(DryRun
));
168 static cl::opt
<bool> Verbose("verbose", cl::Optional
, cl::init(false),
169 cl::desc("Print out each action taken"));
171 static cl::alias
VerboseAlias("v", cl::Optional
,
172 cl::desc("Alias for -verbose"), cl::aliasopt(Verbose
));
174 static cl::opt
<bool> Debug("debug", cl::Optional
, cl::init(false),
175 cl::Hidden
, cl::desc("Print out debugging information"));
177 static cl::alias
DebugAlias("d", cl::Optional
,
178 cl::desc("Alias for -debug"), cl::aliasopt(Debug
));
180 static cl::opt
<bool> TimeActions("time-actions", cl::Optional
, cl::init(false),
181 cl::desc("Print execution time for each action taken"));
183 static cl::opt
<bool> ShowStats("stats", cl::Optional
, cl::init(false),
184 cl::desc("Print statistics accumulated during optimization"));
186 //===----------------------------------------------------------------------===//
187 //=== ADVANCED OPTIONS
188 //===----------------------------------------------------------------------===//
190 static cl::opt
<std::string
> ConfigDir("config-dir", cl::Optional
,
191 cl::desc("Specify configuration directory to override defaults"),
192 cl::value_desc("dir"));
194 static cl::opt
<bool> EmitRawCode("emit-raw-code", cl::Hidden
, cl::Optional
,
195 cl::desc("Emit raw, unoptimized code"));
197 static cl::opt
<bool> PipeCommands("pipe", cl::Optional
,
198 cl::desc("Invoke sub-commands by linking input/output with pipes"));
200 static cl::opt
<bool> KeepTemps("keep-temps", cl::Optional
,
201 cl::desc("Don't delete temporary files created by llvmc"));
203 //===----------------------------------------------------------------------===//
204 //=== POSITIONAL OPTIONS
205 //===----------------------------------------------------------------------===//
207 static cl::list
<std::string
> Files(cl::Positional
, cl::ZeroOrMore
,
208 cl::desc("[Sources/objects/libraries]"));
210 static cl::list
<std::string
> Languages("x", cl::ZeroOrMore
,
211 cl::desc("Specify the source language for subsequent files"),
212 cl::value_desc("language"));
214 //===----------------------------------------------------------------------===//
215 //=== GetFileType - determine type of a file
216 //===----------------------------------------------------------------------===//
217 static const std::string
GetFileType(const std::string
& fname
, unsigned pos
) {
218 static std::vector
<std::string
>::iterator langIt
= Languages
.begin();
219 static std::string CurrLang
= "";
221 // If a -x LANG option has been specified ..
222 if (langIt
!= Languages
.end())
223 // If the -x LANG option came before the current file on command line
224 if (Languages
.getPosition( langIt
- Languages
.begin() ) < pos
) {
226 CurrLang
= *langIt
++;
230 // If there's a current language in effect
231 if (!CurrLang
.empty())
232 return CurrLang
; // use that language
234 // otherwise just determine lang from the filename's suffix
235 return fname
.substr(fname
.rfind('.', fname
.size()) + 1);
238 static void handleTerminatingOptions(CompilerDriver
* CD
) {
239 if (!PrintFileName
.empty()) {
240 sys::Path path
= CD
->GetPathForLinkageItem(PrintFileName
, false);
241 std::string p
= path
.toString();
243 std::cout
<< "Can't locate `" << PrintFileName
<< "'.\n";
245 std::cout
<< p
<< '\n';
250 /// @brief The main program for llvmc
251 int main(int argc
, char **argv
) {
252 llvm_shutdown_obj X
; // Call llvm_shutdown() on exit.
253 // Make sure we print stack trace if we get bad signals
254 sys::PrintStackTraceOnErrorSignal();
258 // Parse the command line options
259 cl::ParseCommandLineOptions(argc
, argv
,
260 " LLVM Compiler Driver (llvmc)\n\n"
261 " This program provides easy invocation of the LLVM tool set\n"
262 " and other compiler tools.\n"
265 // Deal with unimplemented options.
267 throw std::string("Not implemented yet: -pipe");
269 if (OutputFilename
.empty())
270 if (OptLevel
== CompilerDriver::LINKING
)
271 OutputFilename
= "a.out";
273 // Construct the ConfigDataProvider object
274 LLVMC_ConfigDataProvider Provider
;
275 Provider
.setConfigDir(sys::Path(ConfigDir
));
277 // Construct the CompilerDriver object
278 CompilerDriver
* CD
= CompilerDriver::Get(Provider
);
280 // If the LLVM_LIB_SEARCH_PATH environment variable is
281 // set, append it to the list of places to search for libraries
282 char *srchPath
= getenv("LLVM_LIB_SEARCH_PATH");
283 if (srchPath
!= NULL
&& strlen(srchPath
) != 0)
284 LibPaths
.push_back(std::string(srchPath
));
286 // Set the driver flags based on command line options
288 if (Verbose
) flags
|= CompilerDriver::VERBOSE_FLAG
;
289 if (Debug
) flags
|= CompilerDriver::DEBUG_FLAG
;
290 if (DryRun
) flags
|= CompilerDriver::DRY_RUN_FLAG
;
291 if (Native
) flags
|= CompilerDriver::EMIT_NATIVE_FLAG
;
292 if (EmitRawCode
) flags
|= CompilerDriver::EMIT_RAW_FLAG
;
293 if (KeepTemps
) flags
|= CompilerDriver::KEEP_TEMPS_FLAG
;
294 if (ShowStats
) flags
|= CompilerDriver::SHOW_STATS_FLAG
;
295 if (TimeActions
) flags
|= CompilerDriver::TIME_ACTIONS_FLAG
;
296 if (StripOutput
) flags
|= CompilerDriver::STRIP_OUTPUT_FLAG
;
297 CD
->setDriverFlags(flags
);
299 // Specify required parameters
300 CD
->setFinalPhase(FinalPhase
);
301 CD
->setOptimization(OptLevel
);
302 CD
->setOutputMachine(OutputMachine
);
303 CD
->setIncludePaths(Includes
);
304 CD
->setSymbolDefines(Defines
);
305 CD
->setLibraryPaths(LibPaths
);
306 CD
->setfPassThrough(fOpts
);
307 CD
->setMPassThrough(MOpts
);
308 CD
->setWPassThrough(WOpts
);
310 // Provide additional tool arguments
311 if (!PreprocessorToolOpts
.empty())
312 CD
->setPhaseArgs(CompilerDriver::PREPROCESSING
, PreprocessorToolOpts
);
313 if (!TranslatorToolOpts
.empty())
314 CD
->setPhaseArgs(CompilerDriver::TRANSLATION
, TranslatorToolOpts
);
315 if (!OptimizerToolOpts
.empty())
316 CD
->setPhaseArgs(CompilerDriver::OPTIMIZATION
, OptimizerToolOpts
);
317 if (!AssemblerToolOpts
.empty())
318 CD
->setPhaseArgs(CompilerDriver::ASSEMBLY
,AssemblerToolOpts
);
319 if (!LinkerToolOpts
.empty())
320 CD
->setPhaseArgs(CompilerDriver::LINKING
, LinkerToolOpts
);
322 // Check for options that cause us to terminate before any significant work
324 handleTerminatingOptions(CD
);
326 // Prepare the list of files to be compiled by the CompilerDriver.
327 CompilerDriver::InputList InpList
;
328 std::vector
<std::string
>::iterator fileIt
= Files
.begin();
329 std::vector
<std::string
>::iterator libIt
= Libraries
.begin();
330 unsigned libPos
= 0, filePos
= 0;
332 if (libIt
!= Libraries
.end())
333 libPos
= Libraries
.getPosition( libIt
- Libraries
.begin() );
336 if (fileIt
!= Files
.end())
337 filePos
= Files
.getPosition(fileIt
- Files
.begin());
341 if (filePos
!= 0 && (libPos
== 0 || filePos
< libPos
)) {
343 InpList
.push_back(std::make_pair(*fileIt
,
344 GetFileType(*fileIt
, filePos
)));
346 } else if ( libPos
!= 0 && (filePos
== 0 || libPos
< filePos
) ) {
348 InpList
.push_back(std::make_pair(*libIt
++, ""));
351 break; // we're done with the list
354 // Tell the driver to do its thing
356 int result
= CD
->execute(InpList
, sys::Path(OutputFilename
), ErrMsg
);
358 std::cerr
<< argv
[0] << ": " << ErrMsg
<< '\n';
362 // All is good, return success
364 } catch (const std::string
& msg
) {
365 std::cerr
<< argv
[0] << ": " << msg
<< '\n';
367 std::cerr
<< argv
[0] << ": Unexpected unknown exception occurred.\n";