diff options
Diffstat (limited to 'tools/llvmc/CompilerDriver.cpp')
-rw-r--r-- | tools/llvmc/CompilerDriver.cpp | 194 |
1 files changed, 163 insertions, 31 deletions
diff --git a/tools/llvmc/CompilerDriver.cpp b/tools/llvmc/CompilerDriver.cpp index ff63b2100e..038274b72a 100644 --- a/tools/llvmc/CompilerDriver.cpp +++ b/tools/llvmc/CompilerDriver.cpp @@ -13,6 +13,7 @@ //===------------------------------------------------------------------------=== #include "CompilerDriver.h" +#include "ConfigLexer.h" #include <iostream> using namespace llvm; @@ -32,7 +33,7 @@ namespace { const char OutputSuffix[] = ".o"; - void WriteAction(CompilerDriver::Action* a) { + void WriteAction(CompilerDriver::Action* a ) { std::cerr << a->program; std::vector<std::string>::iterator I = a->args.begin(); while (I != a->args.end()) { @@ -42,24 +43,32 @@ namespace { std::cerr << "\n"; } + void DumpAction(CompilerDriver::Action* a) { + std::cerr << "command = " << a->program; + std::vector<std::string>::iterator I = a->args.begin(); + while (I != a->args.end()) { + std::cerr << " " + *I; + ++I; + } + std::cerr << "\n"; + std::cerr << "flags = " << a->flags << "\n"; + std::cerr << "inputAt = " << a->inputAt << "\n"; + std::cerr << "outputAt = " << a->outputAt << "\n"; + } + void DumpConfigData(CompilerDriver::ConfigData* cd, const std::string& type ){ std::cerr << "Configuration Data For '" << cd->langName << "' (" << type << ")\n"; - std::cerr << "translator.preprocesses=" << cd->TranslatorPreprocesses - << "\n"; - std::cerr << "translator.groks_dash_O=" << cd->TranslatorGroksDashO << "\n"; - std::cerr << "translator.optimizes=" << cd->TranslatorOptimizes << "\n"; - std::cerr << "preprocessor.needed=" << cd->PreprocessorNeeded << "\n"; std::cerr << "PreProcessor: "; - WriteAction(&cd->PreProcessor); + DumpAction(&cd->PreProcessor); std::cerr << "Translator: "; - WriteAction(&cd->Translator); + DumpAction(&cd->Translator); std::cerr << "Optimizer: "; - WriteAction(&cd->Optimizer); + DumpAction(&cd->Optimizer); std::cerr << "Assembler: "; - WriteAction(&cd->Assembler); + DumpAction(&cd->Assembler); std::cerr << "Linker: "; - WriteAction(&cd->Linker); + DumpAction(&cd->Linker); } } @@ -75,16 +84,26 @@ CompilerDriver::CompilerDriver(ConfigDataProvider& confDatProv ) , emitRawCode(false) , emitNativeCode(false) , machine() - , libPaths() + , LibraryPaths() + , PreprocessorOptions() + , TranslatorOptions() + , OptimizerOptions() + , AssemblerOptions() + , LinkerOptions() { // FIXME: These libraries are platform specific - libPaths.push_back("/lib"); - libPaths.push_back("/usr/lib"); + LibraryPaths.push_back("/lib"); + LibraryPaths.push_back("/usr/lib"); } CompilerDriver::~CompilerDriver() { cdp = 0; - libPaths.clear(); + LibraryPaths.clear(); + PreprocessorOptions.clear(); + TranslatorOptions.clear(); + OptimizerOptions.clear(); + AssemblerOptions.clear(); + LinkerOptions.clear(); } void CompilerDriver::error( const std::string& errmsg ) { @@ -92,12 +111,27 @@ void CompilerDriver::error( const std::string& errmsg ) { exit(1); } +inline std::string makeDashO(CompilerDriver::OptimizationLevels lev) { + if (lev == CompilerDriver::OPT_NONE) return ""; + std::string result("-O"); + switch (lev) { + case CompilerDriver::OPT_FAST_COMPILE : result.append("1"); break; + case CompilerDriver::OPT_SIMPLE: result.append("2"); break; + case CompilerDriver::OPT_AGGRESSIVE: result.append("3"); break; + case CompilerDriver::OPT_LINK_TIME: result.append("4"); break; + case CompilerDriver::OPT_AGGRESSIVE_LINK_TIME: result.append("5"); break; + default: assert(!"Invalid optimization level!"); + } + return result; +} + CompilerDriver::Action* CompilerDriver::GetAction(ConfigData* cd, const std::string& input, const std::string& output, Phases phase) { Action* pat = 0; + // Get the action pattern switch (phase) { case PREPROCESSING: pat = &cd->PreProcessor; break; case TRANSLATION: pat = &cd->Translator; break; @@ -109,11 +143,57 @@ CompilerDriver::Action* CompilerDriver::GetAction(ConfigData* cd, break; } assert(pat != 0 && "Invalid command pattern"); + + // Create the resulting action Action* a = new Action(*pat); + + // Replace the substitution arguments if (pat->inputAt < a->args.size()) a->args[pat->inputAt] = input; if (pat->outputAt < a->args.size()) a->args[pat->outputAt] = output; + + // Insert specific options for each kind of action type + switch (phase) { + case PREPROCESSING: + a->args.insert(a->args.begin(), PreprocessorOptions.begin(), + PreprocessorOptions.end()); + break; + case TRANSLATION: + a->args.insert(a->args.begin(), TranslatorOptions.begin(), + TranslatorOptions.end()); + if (a->isSet(GROKS_DASH_O_FLAG)) + a->args.insert(a->args.begin(), makeDashO(optLevel)); + else if (a->isSet(GROKS_O10N_FLAG)) + a->args.insert(a->args.begin(), cd->opts[optLevel].begin(), + cd->opts[optLevel].end()); + break; + case OPTIMIZATION: + a->args.insert(a->args.begin(), OptimizerOptions.begin(), + OptimizerOptions.end()); + if (a->isSet(GROKS_DASH_O_FLAG)) + a->args.insert(a->args.begin(), makeDashO(optLevel)); + else if (a->isSet(GROKS_O10N_FLAG)) + a->args.insert(a->args.begin(), cd->opts[optLevel].begin(), + cd->opts[optLevel].end()); + break; + case ASSEMBLY: + a->args.insert(a->args.begin(), AssemblerOptions.begin(), + AssemblerOptions.end()); + break; + case LINKING: + a->args.insert(a->args.begin(), LinkerOptions.begin(), + LinkerOptions.end()); + if (a->isSet(GROKS_DASH_O_FLAG)) + a->args.insert(a->args.begin(), makeDashO(optLevel)); + else if (a->isSet(GROKS_O10N_FLAG)) + a->args.insert(a->args.begin(), cd->opts[optLevel].begin(), + cd->opts[optLevel].end()); + break; + default: + assert(!"Invalid driver phase!"); + break; + } return a; } @@ -122,18 +202,20 @@ void CompilerDriver::DoAction(Action*a) if (isVerbose) WriteAction(a); if (!isDryRun) { - std::cerr << "execve(\"" << a->program << "\",[\n"; + std::cerr << "execve(\"" << a->program << "\",[\""; std::vector<std::string>::iterator I = a->args.begin(); while (I != a->args.end()) { - std::cerr << " \"" << *I << "\",\n"; + std::cerr << *I; ++I; + if (I != a->args.end()) + std::cerr << "\",\""; } - std::cerr << "],ENV);\n"; + std::cerr << "\"],ENV);\n"; } } int CompilerDriver::execute(const InputList& InpList, - const std::string& Output ) { + const sys::Path& Output ) { // Echo the configuration of options if we're running verbose if (isDebug) { @@ -162,8 +244,17 @@ int CompilerDriver::execute(const InputList& InpList, if (finalPhase == LINKING && Output.empty()) error("An output file name must be specified for linker output"); + // This vector holds all the resulting actions of the following loop. std::vector<Action*> actions; + // Create a temporary directory for our temporary files + sys::Path TempDir(sys::Path::CONSTRUCT_TEMP_DIR); + sys::Path TempPreprocessorOut; + sys::Path TempTranslatorOut; + sys::Path TempOptimizerOut; + sys::Path TempAssemblerOut; + sys::Path TempLinkerOut; + /// PRE-PROCESSING / TRANSLATION / OPTIMIZATION / ASSEMBLY phases // for each input item std::vector<std::string> LinkageItems; @@ -207,28 +298,59 @@ int CompilerDriver::execute(const InputList& InpList, OutFile = Output; } - /// PRE-PROCESSING PHASE - if (finalPhase == PREPROCESSING) { - if (cd->PreProcessor.program.empty()) - error(cd->langName + " does not support pre-processing"); - else - actions.push_back(GetAction(cd,I->first,OutFile,PREPROCESSING)); - } else if (cd->PreprocessorNeeded && !cd->TranslatorPreprocesses) { - if (!cd->PreProcessor.program.empty()) { - actions.push_back(GetAction(cd,I->first,OutFile,PREPROCESSING)); + // PRE-PROCESSING PHASE + Action& a = cd->PreProcessor; + + // Get the preprocessing action, if needed, or error if appropriate + if (!a.program.empty()) { + if (a.isSet(REQUIRED_FLAG) || finalPhase == PREPROCESSING) { + TempPreprocessorOut = TempDir; + TempPreprocessorOut.append_file("preproc.out"); + actions.push_back(GetAction(cd,I->first, + TempPreprocessorOut,PREPROCESSING)); } + } else if (finalPhase == PREPROCESSING) { + error(cd->langName + " does not support pre-processing"); + } else if (a.isSet(REQUIRED_FLAG)) { + error(std::string("Don't know how to pre-process ") + + cd->langName + " files"); } - // Short-circuit remaining actions if all they want is pre-processing if (finalPhase == PREPROCESSING) { ++I; continue; }; /// TRANSLATION PHASE - actions.push_back(GetAction(cd,I->first,OutFile,TRANSLATION)); + a = cd->Translator; + + // Get the translation action, if needed, or error if appropriate + if (!a.program.empty()) { + if (a.isSet(REQUIRED_FLAG) || finalPhase == TRANSLATION) { + TempTranslatorOut = TempDir; + TempTranslatorOut.append_file("trans.out"); + actions.push_back(GetAction(cd,I->first,TempTranslatorOut,TRANSLATION)); + } + } else if (finalPhase == TRANSLATION) { + error(cd->langName + " does not support translation"); + } else if (a.isSet(REQUIRED_FLAG)) { + error(std::string("Don't know how to translate ") + + cd->langName + " files"); + } // Short-circuit remaining actions if all they want is translation if (finalPhase == TRANSLATION) { ++I; continue; } /// OPTIMIZATION PHASE - actions.push_back(GetAction(cd,I->first,OutFile,OPTIMIZATION)); + a = cd->Optimizer; + + // Get the optimization action, if needed, or error if appropriate + if (!a.program.empty()) { + TempOptimizerOut = TempDir; + TempOptimizerOut.append_file("trans.out"); + actions.push_back(GetAction(cd,I->first,TempOptimizerOut,OPTIMIZATION)); + } else if (finalPhase == OPTIMIZATION) { + error(cd->langName + " does not support optimization"); + } else if (a.isSet(REQUIRED_FLAG)) { + error(std::string("Don't know how to optimize ") + + cd->langName + " files"); + } // Short-circuit remaining actions if all they want is optimization if (finalPhase == OPTIMIZATION) { ++I; continue; } @@ -244,6 +366,16 @@ int CompilerDriver::execute(const InputList& InpList, aIter++; } + // Cleanup files + if (TempPreprocessorOut.exists()) + TempPreprocessorOut.remove_file(); + if (TempTranslatorOut.exists()) + TempTranslatorOut.remove_file(); + if (TempOptimizerOut.exists()) + TempOptimizerOut.remove_file(); + if (TempDir.exists()) + TempDir.remove_directory(); + return 0; } |