summaryrefslogtreecommitdiff
path: root/tools/llvmc/CompilerDriver.cpp
diff options
context:
space:
mode:
authorReid Spencer <rspencer@reidspencer.com>2004-08-13 20:22:43 +0000
committerReid Spencer <rspencer@reidspencer.com>2004-08-13 20:22:43 +0000
commit5c56dc1f6215d49cc66960baab29a9074bf6e165 (patch)
tree20cb2b0e5b17b68e1a730d07131904081fcd34ec /tools/llvmc/CompilerDriver.cpp
parent2594c9abbf1301d204782cbab1a0a4e392ddbe88 (diff)
downloadllvm-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.cpp227
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