diff options
author | Reid Spencer <rspencer@reidspencer.com> | 2004-08-13 20:22:43 +0000 |
---|---|---|
committer | Reid Spencer <rspencer@reidspencer.com> | 2004-08-13 20:22:43 +0000 |
commit | 5c56dc1f6215d49cc66960baab29a9074bf6e165 (patch) | |
tree | 20cb2b0e5b17b68e1a730d07131904081fcd34ec /tools/llvmc/CompilerDriver.cpp | |
parent | 2594c9abbf1301d204782cbab1a0a4e392ddbe88 (diff) | |
download | llvm-5c56dc1f6215d49cc66960baab29a9074bf6e165.tar.gz llvm-5c56dc1f6215d49cc66960baab29a9074bf6e165.tar.bz2 llvm-5c56dc1f6215d49cc66960baab29a9074bf6e165.tar.xz |
Additional functionality. This version handles option parsing and parameter
subsitution correctly for at least .ll and .st files. There's still a long
way to go (i.e. this isn't worth of review yet).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15728 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvmc/CompilerDriver.cpp')
-rw-r--r-- | tools/llvmc/CompilerDriver.cpp | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/tools/llvmc/CompilerDriver.cpp b/tools/llvmc/CompilerDriver.cpp new file mode 100644 index 0000000000..7a639b38cd --- /dev/null +++ b/tools/llvmc/CompilerDriver.cpp @@ -0,0 +1,227 @@ +//===- DriverAction.cpp - Compile Driver Actions ----------------*- C++ -*-===// +// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements support for executable actions in the LLVM Compiler +// Driver (llvmc). +// +//===------------------------------------------------------------------------=== + +#include "CompilerDriver.h" +#include <iostream> + +using namespace llvm; + +namespace { + inline std::string RemoveSuffix(const std::string& fullName) { + size_t dotpos = fullName.rfind('.',fullName.size()); + if ( dotpos == std::string::npos ) return fullName; + return fullName.substr(0, dotpos); + } + + inline std::string GetSuffix(const std::string& fullName) { + size_t dotpos = fullName.rfind('.',fullName.size()); + if ( dotpos = std::string::npos ) return ""; + return fullName.substr(dotpos+1); + } + const char OutputSuffix[] = ".o"; + +} + + +CompilerDriver::CompilerDriver(ConfigDataProvider& confDatProv ) + : cdp(&confDatProv) + , finalPhase(LINKING) + , optLevel(OPT_FAST_COMPILE) + , isDryRun(false) + , isVerbose(false) + , isDebug(false) + , timeActions(false) + , emitRawCode(false) + , emitNativeCode(false) + , machine() + , libPaths() +{ + // FIXME: These libraries are platform specific + libPaths.push_back("/lib"); + libPaths.push_back("/usr/lib"); +} + +CompilerDriver::~CompilerDriver() { + cdp = 0; + libPaths.clear(); +} + +void CompilerDriver::error( const std::string& errmsg ) { + std::cerr << "Error: " << errmsg << ".\n"; + exit(1); +} + +CompilerDriver::Action* CompilerDriver::GetAction(ConfigData* cd, + const std::string& input, + const std::string& output, + Phases phase) +{ + Action* pat = 0; + switch (phase) { + case PREPROCESSING: pat = &cd->PreProcessor; break; + case TRANSLATION: pat = &cd->Translator; break; + case OPTIMIZATION: pat = &cd->Optimizer; break; + case ASSEMBLY: pat = &cd->Assembler; break; + case LINKING: pat = &cd->Linker; break; + default: + assert(!"Invalid driver phase!"); + break; + } + assert(pat != 0 && "Invalid command pattern"); + Action* a = new Action(*pat); + a->args[pat->inputAt] = input; + a->args[pat->outputAt] = output; + return a; +} + +void CompilerDriver::WriteAction(Action* a) { + std::cerr << a->program; + std::vector<std::string>::iterator I = a->args.begin(); + while (I != a->args.end()) { + std::cerr << " " + *I; + ++I; + } + std::cerr << "\n"; +} + +void CompilerDriver::DoAction(Action*a) +{ + if (isVerbose) + WriteAction(a); + if (!isDryRun) { + std::cerr << "execve(\"" << a->program << "\",[\n"; + std::vector<std::string>::iterator I = a->args.begin(); + while (I != a->args.end()) { + std::cerr << " \"" << *I << "\",\n"; + ++I; + } + std::cerr << "],ENV);\n"; + } +} + +int CompilerDriver::execute(const InputList& InpList, + const std::string& Output ) { + // Echo the configuration of options if we're running verbose + if (isDebug) + { + std::cerr << "Compiler Driver Options:\n"; + std::cerr << "DryRun = " << isDryRun << "\n"; + std::cerr << "Verbose = " << isVerbose << " \n"; + std::cerr << "TimeActions = " << timeActions << "\n"; + std::cerr << "EmitRawCode = " << emitRawCode << "\n"; + std::cerr << "OutputMachine = " << machine << "\n"; + std::cerr << "EmitNativeCode = " << emitNativeCode << "\n"; + InputList::const_iterator I = InpList.begin(); + while ( I != InpList.end() ) { + std::cerr << "Input: " << I->first << "(" << I->second << ")\n"; + ++I; + } + std::cerr << "Output: " << Output << "\n"; + } + + // If there's no input, we're done. + if (InpList.empty()) + error("Nothing to compile."); + + // If they are asking for linking and didn't provide an output + // file then its an error (no way for us to "make up" a meaningful + // file name based on the various linker input files). + if (finalPhase == LINKING && Output.empty()) + error("An output file name must be specified for linker output"); + + std::vector<Action*> actions; + + /// PRE-PROCESSING / TRANSLATION / OPTIMIZATION / ASSEMBLY phases + // for each input item + std::vector<std::string> LinkageItems; + InputList::const_iterator I = InpList.begin(); + while ( I != InpList.end() ) { + // Get the suffix of the file name + std::string suffix = GetSuffix(I->first); + + // If its a library, bytecode file, or object file, save + // it for linking below and short circuit the + // pre-processing/translation/assembly phases + if (I->second.empty() || suffix == "o" || suffix == "bc") { + // We shouldn't get any of these types of files unless we're + // later going to link. Enforce this limit now. + if (finalPhase != LINKING) { + error("Pre-compiled objects found but linking not requested"); + } + LinkageItems.push_back(I->first); + continue; // short circuit remainder of loop + } + + // At this point, we know its something we need to translate + // and/or optimize. See if we can get the configuration data + // for this kind of file. + ConfigData* cd = cdp->ProvideConfigData(I->second); + if (cd == 0) + error(std::string("Files of type '") + I->second + + "' are not recognized." ); + + // We have valid configuration data, now figure out where the output + // of compilation should end up. + std::string OutFile; + if (finalPhase != LINKING) { + if (InpList.size() == 1 && !Output.empty()) + OutFile = Output; + else + OutFile = RemoveSuffix(I->first) + OutputSuffix; + } else { + 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)); + } + } + + // 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)); + // 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)); + // Short-circuit remaining actions if all they want is optimization + if (finalPhase == OPTIMIZATION) { ++I; continue; } + + ++I; + } + + /// LINKING PHASE + + /// RUN THE ACTIONS + std::vector<Action*>::iterator aIter = actions.begin(); + while (aIter != actions.end()) { + DoAction(*aIter); + aIter++; + } + + return 0; +} + +// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab |