1 //===- CompilerDriver.cpp - The LLVM Compiler Driver ------------*- C++ -*-===//
4 // The LLVM Compiler Infrastructure
6 // This file was developed by Reid Spencer and is distributed under the
7 // University of Illinois Open Source License. See LICENSE.TXT for details.
9 //===----------------------------------------------------------------------===//
11 // This file implements the bulk of the LLVM Compiler Driver (llvmc).
13 //===------------------------------------------------------------------------===
15 #include "CompilerDriver.h"
16 #include "ConfigLexer.h"
17 #include "llvm/Bytecode/Reader.h"
18 #include "llvm/Module.h"
19 #include "Support/FileUtilities.h"
20 #include "Support/SystemUtils.h"
21 #include "Support/StringExtras.h"
27 inline std::string RemoveSuffix(const std::string& fullName) {
28 size_t dotpos = fullName.rfind('.',fullName.size());
29 if ( dotpos == std::string::npos ) return fullName;
30 return fullName.substr(0, dotpos);
33 const char OutputSuffix[] = ".o";
35 void WriteAction(CompilerDriver::Action* action ) {
36 std::cerr << action->program;
37 std::vector<std::string>::iterator I = action->args.begin();
38 while (I != action->args.end()) {
39 std::cerr << " " + *I;
45 void DumpAction(CompilerDriver::Action* action) {
46 std::cerr << "command = " << action->program;
47 std::vector<std::string>::iterator I = action->args.begin();
48 while (I != action->args.end()) {
49 std::cerr << " " + *I;
53 std::cerr << "flags = " << action->flags << "\n";
56 void DumpConfigData(CompilerDriver::ConfigData* cd, const std::string& type ){
57 std::cerr << "Configuration Data For '" << cd->langName << "' (" << type
59 std::cerr << "PreProcessor: ";
60 DumpAction(&cd->PreProcessor);
61 std::cerr << "Translator: ";
62 DumpAction(&cd->Translator);
63 std::cerr << "Optimizer: ";
64 DumpAction(&cd->Optimizer);
65 std::cerr << "Assembler: ";
66 DumpAction(&cd->Assembler);
67 std::cerr << "Linker: ";
68 DumpAction(&cd->Linker);
71 /// This specifies the passes to run for OPT_FAST_COMPILE (-O1)
72 /// which should reduce the volume of code and make compilation
73 /// faster. This is also safe on any llvm module.
74 static const char* DefaultFastCompileOptimizations[] = {
75 "-simplifycfg", "-mem2reg", "-instcombine"
79 // Stuff in this namespace properly belongs in lib/System and needs
80 // to be portable but we're avoiding that for now.
83 bool FileIsReadable(const std::string& fname) {
84 return 0 == access(fname.c_str(), F_OK | R_OK);
87 void CleanupTempFile(const std::string& fname) {
88 if (FileIsReadable(fname))
89 unlink(fname.c_str());
92 std::string MakeTemporaryDirectory() {
94 strcpy(temp_name,"/tmp/llvm_XXXXXX");
95 if (0 == mkdtemp(temp_name))
96 throw std::string("Can't create temporary directory");
100 std::string FindExecutableInPath(const std::string& program) {
101 // First, just see if the program is already executable
102 if (isExecutableFile(program)) return program;
104 // Get the path. If its empty, we can't do anything
105 const char *PathStr = getenv("PATH");
106 if (PathStr == 0) return "";
108 // Now we have a colon separated list of directories to search; try them.
109 unsigned PathLen = strlen(PathStr);
111 // Find the first colon...
112 const char *Colon = std::find(PathStr, PathStr+PathLen, ':');
114 // Check to see if this first directory contains the executable...
115 std::string FilePath = std::string(PathStr, Colon) + '/' + program;
116 if (isExecutableFile(FilePath))
117 return FilePath; // Found the executable!
119 // Nope it wasn't in this directory, check the next range!
120 PathLen -= Colon-PathStr;
123 // Advance past duplicate coons
124 while (*PathStr == ':') {
130 // If we fell out, we ran out of directories in PATH to search, return failure
135 CompilerDriver::CompilerDriver(ConfigDataProvider& confDatProv )
137 , finalPhase(LINKING)
138 , optLevel(OPT_FAST_COMPILE)
144 , emitNativeCode(false)
151 // FIXME: These libraries are platform specific
152 LibraryPaths.push_back("/lib");
153 LibraryPaths.push_back("/usr/lib");
154 AdditionalArgs.reserve(NUM_PHASES);
155 StringVector emptyVec;
156 for (unsigned i = 0; i < NUM_PHASES; ++i)
157 AdditionalArgs.push_back(emptyVec);
160 CompilerDriver::~CompilerDriver() {
162 LibraryPaths.clear();
163 AdditionalArgs.clear();
166 CompilerDriver::ConfigData::ConfigData()
174 StringVector emptyVec;
175 for (unsigned i = 0; i < NUM_PHASES; ++i)
176 opts.push_back(emptyVec);
179 void CompilerDriver::error( const std::string& errmsg ) {
180 std::cerr << "llvmc: Error: " << errmsg << ".\n";
184 CompilerDriver::Action* CompilerDriver::GetAction(ConfigData* cd,
185 const std::string& input,
186 const std::string& output,
189 Action* pat = 0; ///< The pattern/template for the action
190 Action* action = new Action; ///< The actual action to execute
192 // Get the action pattern
194 case PREPROCESSING: pat = &cd->PreProcessor; break;
195 case TRANSLATION: pat = &cd->Translator; break;
196 case OPTIMIZATION: pat = &cd->Optimizer; break;
197 case ASSEMBLY: pat = &cd->Assembler; break;
198 case LINKING: pat = &cd->Linker; break;
200 assert(!"Invalid driver phase!");
203 assert(pat != 0 && "Invalid command pattern");
205 // Copy over some pattern things that don't need to change
206 action->program = pat->program;
207 action->flags = pat->flags;
209 // Do the substitutions from the pattern to the actual
210 StringVector::iterator PI = pat->args.begin();
211 StringVector::iterator PE = pat->args.end();
213 if ((*PI)[0] == '%') {
215 action->args.push_back(input);
216 } else if (*PI == "%out%") {
217 action->args.push_back(output);
218 } else if (*PI == "%time%") {
220 action->args.push_back("-time-passes");
221 } else if (*PI == "%stats%") {
223 action->args.push_back("-stats");
224 } else if (*PI == "%target%") {
225 // FIXME: Ignore for now
226 } else if (*PI == "%opt%") {
228 if (cd->opts.size() > static_cast<unsigned>(optLevel) &&
229 !cd->opts[optLevel].empty())
230 action->args.insert(action->args.end(), cd->opts[optLevel].begin(),
231 cd->opts[optLevel].end());
233 error("Optimization options for level " + utostr(unsigned(optLevel)) +
234 " were not specified");
236 } else if (*PI == "%args%") {
237 if (AdditionalArgs.size() > unsigned(phase))
238 if (!AdditionalArgs[phase].empty()) {
239 // Get specific options for each kind of action type
240 StringVector& addargs = AdditionalArgs[phase];
241 // Add specific options for each kind of action type
242 action->args.insert(action->args.end(), addargs.begin(), addargs.end());
245 error("Invalid substitution name" + *PI);
248 // Its not a substitution, just put it in the action
249 action->args.push_back(*PI);
255 // Finally, we're done
259 bool CompilerDriver::DoAction(Action*action) {
260 assert(action != 0 && "Invalid Action!");
264 std::string prog(sys::FindExecutableInPath(action->program));
266 error("Can't find program '" + action->program + "'");
268 // Get the program's arguments
269 const char* argv[action->args.size() + 1];
270 argv[0] = prog.c_str();
272 for (; i <= action->args.size(); ++i)
273 argv[i] = action->args[i-1].c_str();
276 // Invoke the program
277 return !ExecWait(argv, environ);
282 int CompilerDriver::execute(const InputList& InpList,
283 const std::string& Output ) {
284 // Echo the configuration of options if we're running verbose
287 std::cerr << "Compiler Driver Options:\n";
288 std::cerr << "DryRun = " << isDryRun << "\n";
289 std::cerr << "Verbose = " << isVerbose << " \n";
290 std::cerr << "TimeActions = " << timeActions << "\n";
291 std::cerr << "EmitRawCode = " << emitRawCode << "\n";
292 std::cerr << "OutputMachine = " << machine << "\n";
293 std::cerr << "EmitNativeCode = " << emitNativeCode << "\n";
294 InputList::const_iterator I = InpList.begin();
295 while ( I != InpList.end() ) {
296 std::cerr << "Input: " << I->first << "(" << I->second << ")\n";
299 std::cerr << "Output: " << Output << "\n";
302 // If there's no input, we're done.
304 error("Nothing to compile.");
306 // If they are asking for linking and didn't provide an output
307 // file then its an error (no way for us to "make up" a meaningful
308 // file name based on the various linker input files).
309 if (finalPhase == LINKING && Output.empty())
310 error("An output file name must be specified for linker output");
312 // This vector holds all the resulting actions of the following loop.
313 std::vector<Action*> actions;
315 // Create a temporary directory for our temporary files
316 std::string TempDir(sys::MakeTemporaryDirectory());
317 std::string TempPreprocessorOut(TempDir + "/preproc.o");
318 std::string TempTranslatorOut(TempDir + "/trans.o");
319 std::string TempOptimizerOut(TempDir + "/opt.o");
320 std::string TempAssemblerOut(TempDir + "/asm.o");
322 /// PRE-PROCESSING / TRANSLATION / OPTIMIZATION / ASSEMBLY phases
323 // for each input item
324 std::vector<std::string> LinkageItems;
325 std::string OutFile(Output);
326 InputList::const_iterator I = InpList.begin();
327 while ( I != InpList.end() ) {
328 // Get the suffix of the file name
329 const std::string& ftype = I->second;
331 // If its a library, bytecode file, or object file, save
332 // it for linking below and short circuit the
333 // pre-processing/translation/assembly phases
334 if (ftype.empty() || ftype == "o" || ftype == "bc") {
335 // We shouldn't get any of these types of files unless we're
336 // later going to link. Enforce this limit now.
337 if (finalPhase != LINKING) {
338 error("Pre-compiled objects found but linking not requested");
340 LinkageItems.push_back(I->first);
341 ++I; continue; // short circuit remainder of loop
344 // At this point, we know its something we need to translate
345 // and/or optimize. See if we can get the configuration data
346 // for this kind of file.
347 ConfigData* cd = cdp->ProvideConfigData(I->second);
349 error(std::string("Files of type '") + I->second +
350 "' are not recognized." );
352 DumpConfigData(cd,I->second);
354 // Initialize the input file
355 std::string InFile(I->first);
357 // PRE-PROCESSING PHASE
358 Action& action = cd->PreProcessor;
360 // Get the preprocessing action, if needed, or error if appropriate
361 if (!action.program.empty()) {
362 if (action.isSet(REQUIRED_FLAG) || finalPhase == PREPROCESSING) {
363 if (finalPhase == PREPROCESSING)
364 actions.push_back(GetAction(cd,InFile,OutFile,PREPROCESSING));
366 actions.push_back(GetAction(cd,InFile,TempPreprocessorOut,
368 InFile = TempPreprocessorOut;
371 } else if (finalPhase == PREPROCESSING) {
372 error(cd->langName + " does not support pre-processing");
373 } else if (action.isSet(REQUIRED_FLAG)) {
374 error(std::string("Don't know how to pre-process ") +
375 cd->langName + " files");
378 // Short-circuit remaining actions if all they want is pre-processing
379 if (finalPhase == PREPROCESSING) { ++I; continue; };
381 /// TRANSLATION PHASE
382 action = cd->Translator;
384 // Get the translation action, if needed, or error if appropriate
385 if (!action.program.empty()) {
386 if (action.isSet(REQUIRED_FLAG) || finalPhase == TRANSLATION) {
387 if (finalPhase == TRANSLATION)
388 actions.push_back(GetAction(cd,InFile,OutFile,TRANSLATION));
390 actions.push_back(GetAction(cd,InFile,TempTranslatorOut,TRANSLATION));
391 InFile = TempTranslatorOut;
395 if (action.isSet(OUTPUT_IS_ASM_FLAG)) {
396 /// The output of the translator is an LLVM Assembly program
397 /// We need to translate it to bytecode
398 Action* action = new Action();
399 action->program = "llvm-as";
400 action->args.push_back(InFile);
401 action->args.push_back("-o");
403 action->args.push_back(InFile);
404 actions.push_back(action);
407 } else if (finalPhase == TRANSLATION) {
408 error(cd->langName + " does not support translation");
409 } else if (action.isSet(REQUIRED_FLAG)) {
410 error(std::string("Don't know how to translate ") +
411 cd->langName + " files");
414 // Short-circuit remaining actions if all they want is translation
415 if (finalPhase == TRANSLATION) { ++I; continue; }
417 /// OPTIMIZATION PHASE
418 action = cd->Optimizer;
420 // Get the optimization action, if needed, or error if appropriate
422 if (!action.program.empty()) {
423 if (action.isSet(REQUIRED_FLAG) || finalPhase == OPTIMIZATION) {
424 if (finalPhase == OPTIMIZATION)
425 actions.push_back(GetAction(cd,InFile,OutFile,OPTIMIZATION));
427 actions.push_back(GetAction(cd,InFile,TempOptimizerOut,OPTIMIZATION));
428 InFile = TempOptimizerOut;
431 if (action.isSet(OUTPUT_IS_ASM_FLAG)) {
432 /// The output of the translator is an LLVM Assembly program
433 /// We need to translate it to bytecode
434 Action* action = new Action();
435 action->program = "llvm-as";
436 action->args.push_back(InFile);
437 action->args.push_back("-f");
438 action->args.push_back("-o");
440 action->args.push_back(InFile);
441 actions.push_back(action);
444 } else if (finalPhase == OPTIMIZATION) {
445 error(cd->langName + " does not support optimization");
446 } else if (action.isSet(REQUIRED_FLAG)) {
447 error(std::string("Don't know how to optimize ") +
448 cd->langName + " files");
452 // Short-circuit remaining actions if all they want is optimization
453 if (finalPhase == OPTIMIZATION) { ++I; continue; }
456 action = cd->Assembler;
458 if (finalPhase == ASSEMBLY || emitNativeCode) {
459 if (emitNativeCode) {
460 if (action.program.empty()) {
461 error(std::string("Native Assembler not specified for ") +
462 cd->langName + " files");
463 } else if (finalPhase == ASSEMBLY) {
464 actions.push_back(GetAction(cd,InFile,OutFile,ASSEMBLY));
466 actions.push_back(GetAction(cd,InFile,TempAssemblerOut,ASSEMBLY));
467 InFile = TempAssemblerOut;
470 // Just convert back to llvm assembly with llvm-dis
471 Action* action = new Action();
472 action->program = "llvm-dis";
473 action->args.push_back(InFile);
474 action->args.push_back("-f");
475 action->args.push_back("-o");
476 action->args.push_back(OutFile);
477 actions.push_back(action);
481 // Short-circuit remaining actions if all they want is assembly output
482 if (finalPhase == ASSEMBLY) { ++I; continue; }
484 // Register the OutFile as a link candidate
485 LinkageItems.push_back(InFile);
487 // Go to next file to be processed
492 if (finalPhase == LINKING) {
493 if (emitNativeCode) {
494 error("llvmc doesn't know how to link native code yet");
496 // First, we need to examine the files to ensure that they all contain
497 // bytecode files. Since the final output is bytecode, we can only
499 StringVector::const_iterator I = LinkageItems.begin();
500 StringVector::const_iterator E = LinkageItems.end();
501 StringVector lib_list;
503 if (sys::FileIsReadable(*I)) {
504 if (CheckMagic(*I, "llvm")) {
505 // Examine the bytecode file for additional bytecode libraries to
507 ModuleProvider* mp = getBytecodeModuleProvider(*I);
508 assert(mp!=0 && "Couldn't get module provider from bytecode file");
509 Module* M = mp->releaseModule();
510 assert(M!=0 && "Couldn't get module from module provider");
511 Module::lib_iterator LI = M->lib_begin();
512 Module::lib_iterator LE = M->lib_end();
514 if (sys::FileIsReadable(*LI)) {
515 if (CheckMagic(*I,"llvm")) {
516 lib_list.push_back(*LI);
518 error(std::string("Library '") + *LI + "' required by file '"
519 + *I + "' is not an LLVM bytecode file");
522 error(std::string("Library '") + *LI + "' required by file '"
523 + *I + "' is not readable");
528 error(std::string("File '") + *I + " is not an LLVM byte code file");
531 error(std::string("File '") + *I + " is not readable");
536 // We're emitting bytecode so let's build an llvm-link Action
537 Action* link = new Action();
538 link->program = "llvm-link";
539 link->args = LinkageItems;
540 link->args.insert(link->args.end(), lib_list.begin(), lib_list.end());
541 link->args.push_back("-f");
542 link->args.push_back("-o");
543 link->args.push_back(OutFile);
545 link->args.push_back("-time-passes");
547 link->args.push_back("-stats");
548 actions.push_back(link);
553 std::vector<Action*>::iterator aIter = actions.begin();
554 while (aIter != actions.end()) {
555 if (!DoAction(*aIter))
556 error("Action failed");
562 ::sys::CleanupTempFile(TempPreprocessorOut);
563 ::sys::CleanupTempFile(TempTranslatorOut);
564 ::sys::CleanupTempFile(TempOptimizerOut);
566 // Cleanup temporary directory we created
567 if (::sys::FileIsReadable(TempDir))
568 rmdir(TempDir.c_str());
574 // vim: sw=2 smartindent smarttab tw=80 autoindent expandtab