2004-08-13 22:22:43 +02:00
|
|
|
//===--- llvmc.cpp - The LLVM Compiler Driver -------------------*- C++ -*-===//
|
2004-08-10 18:26:01 +02:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2004-08-13 22:22:43 +02:00
|
|
|
// This file was developed by Reid Spencer and is distributed under the
|
2004-08-10 18:26:01 +02:00
|
|
|
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This tool provides a single point of access to the LLVM compilation tools.
|
|
|
|
// It has many options. To discover the options supported please refer to the
|
|
|
|
// tools' manual page (docs/CommandGuide/html/llvmc.html) or run the tool with
|
|
|
|
// the --help option.
|
|
|
|
//
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
|
2004-08-10 18:29:18 +02:00
|
|
|
#include "CompilerDriver.h"
|
2004-08-13 22:22:43 +02:00
|
|
|
#include "ConfigData.h"
|
2004-08-10 18:26:01 +02:00
|
|
|
#include "llvm/System/Signals.h"
|
|
|
|
#include "Support/CommandLine.h"
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2004-08-13 22:22:43 +02:00
|
|
|
namespace {
|
2004-08-10 18:26:01 +02:00
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
//=== PHASE OPTIONS
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
static cl::opt<CompilerDriver::Phases> FinalPhase(
|
|
|
|
cl::desc("Choose final phase of compilation:"),
|
2004-08-13 22:22:43 +02:00
|
|
|
cl::init(CompilerDriver::LINKING),
|
2004-08-10 18:26:01 +02:00
|
|
|
cl::values(
|
|
|
|
clEnumValN(CompilerDriver::PREPROCESSING,"E",
|
2004-08-13 22:22:43 +02:00
|
|
|
"Stop compilation after pre-processing phase"),
|
|
|
|
clEnumValN(CompilerDriver::TRANSLATION, "t",
|
|
|
|
"Stop compilation after translation phase"),
|
2004-08-10 18:26:01 +02:00
|
|
|
clEnumValN(CompilerDriver::OPTIMIZATION,"c",
|
2004-08-13 22:22:43 +02:00
|
|
|
"Stop compilation after optimization phase"),
|
2004-08-10 18:26:01 +02:00
|
|
|
clEnumValN(CompilerDriver::ASSEMBLY,"S",
|
2004-08-13 22:22:43 +02:00
|
|
|
"Stop compilation after assembly phase"),
|
2004-08-10 18:26:01 +02:00
|
|
|
clEnumValEnd
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
//=== OPTIMIZATION OPTIONS
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
static cl::opt<CompilerDriver::OptimizationLevels> OptLevel(
|
|
|
|
cl::desc("Choose level of optimization to apply:"),
|
2004-08-13 22:22:43 +02:00
|
|
|
cl::init(CompilerDriver::OPT_FAST_COMPILE),
|
2004-08-10 18:26:01 +02:00
|
|
|
cl::values(
|
|
|
|
clEnumValN(CompilerDriver::OPT_FAST_COMPILE,"O0",
|
2004-08-13 22:22:43 +02:00
|
|
|
"An alias for the -O1 option."),
|
2004-08-10 18:26:01 +02:00
|
|
|
clEnumValN(CompilerDriver::OPT_FAST_COMPILE,"O1",
|
|
|
|
"Optimize for compilation speed, not execution speed."),
|
|
|
|
clEnumValN(CompilerDriver::OPT_SIMPLE,"O2",
|
|
|
|
"Perform simple translation time optimizations"),
|
|
|
|
clEnumValN(CompilerDriver::OPT_AGGRESSIVE,"O3",
|
|
|
|
"Perform aggressive translation time optimizations"),
|
|
|
|
clEnumValN(CompilerDriver::OPT_LINK_TIME,"O4",
|
|
|
|
"Perform link time optimizations"),
|
|
|
|
clEnumValN(CompilerDriver::OPT_AGGRESSIVE_LINK_TIME,"O5",
|
|
|
|
"Perform aggressive link time optimizations"),
|
|
|
|
clEnumValEnd
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
//=== TOOL OPTIONS
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
|
|
|
|
static cl::opt<std::string> PPToolOpts("Tpp", cl::ZeroOrMore,
|
2004-08-13 22:22:43 +02:00
|
|
|
cl::desc("Pass specific options to the pre-processor"),
|
|
|
|
cl::value_desc("option"));
|
2004-08-10 18:26:01 +02:00
|
|
|
|
|
|
|
static cl::opt<std::string> AsmToolOpts("Tasm", cl::ZeroOrMore,
|
2004-08-13 22:22:43 +02:00
|
|
|
cl::desc("Pass specific options to the assembler"),
|
|
|
|
cl::value_desc("option"));
|
2004-08-10 18:26:01 +02:00
|
|
|
|
|
|
|
static cl::opt<std::string> OptToolOpts("Topt", cl::ZeroOrMore,
|
2004-08-13 22:22:43 +02:00
|
|
|
cl::desc("Pass specific options to the optimizer"),
|
|
|
|
cl::value_desc("option"));
|
2004-08-10 18:26:01 +02:00
|
|
|
|
|
|
|
static cl::opt<std::string> LinkToolOpts("Tlink", cl::ZeroOrMore,
|
2004-08-13 22:22:43 +02:00
|
|
|
cl::desc("Pass specific options to the linker"),
|
|
|
|
cl::value_desc("option"));
|
2004-08-10 18:26:01 +02:00
|
|
|
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
//=== INPUT OPTIONS
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
|
|
|
|
static cl::list<std::string> LibPaths("L", cl::Prefix,
|
|
|
|
cl::desc("Specify a library search path"), cl::value_desc("directory"));
|
|
|
|
|
|
|
|
static cl::list<std::string> Libraries("l", cl::Prefix,
|
|
|
|
cl::desc("Specify libraries to link to"), cl::value_desc("library prefix"));
|
|
|
|
|
|
|
|
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
//=== OUTPUT OPTIONS
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
|
2004-08-13 22:22:43 +02:00
|
|
|
static cl::opt<std::string> OutputFilename("o",
|
2004-08-10 18:26:01 +02:00
|
|
|
cl::desc("Override output filename"), cl::value_desc("filename"));
|
|
|
|
|
2004-08-13 22:22:43 +02:00
|
|
|
static cl::opt<std::string> OutputMachine("m", cl::Prefix,
|
2004-08-10 18:26:01 +02:00
|
|
|
cl::desc("Specify a target machine"), cl::value_desc("machine"));
|
|
|
|
|
2004-08-13 22:22:43 +02:00
|
|
|
static cl::opt<bool> Native("native", cl::init(false),
|
2004-08-10 18:26:01 +02:00
|
|
|
cl::desc("Generative native object and executables instead of bytecode"));
|
|
|
|
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
//=== INFORMATION OPTIONS
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
|
2004-08-13 22:22:43 +02:00
|
|
|
static cl::opt<bool> DryRun("dry-run", cl::Optional, cl::init(false),
|
|
|
|
cl::desc("Do everything but perform the compilation actions"));
|
2004-08-10 18:26:01 +02:00
|
|
|
|
2004-08-13 22:22:43 +02:00
|
|
|
static cl::alias DryRunAlias("y", cl::Optional,
|
|
|
|
cl::desc("Alias for -dry-run"), cl::aliasopt(DryRun));
|
2004-08-10 18:26:01 +02:00
|
|
|
|
2004-08-13 22:22:43 +02:00
|
|
|
static cl::opt<bool> Verbose("verbose", cl::Optional, cl::init(false),
|
2004-08-10 18:26:01 +02:00
|
|
|
cl::desc("Print out each action taken"));
|
|
|
|
|
2004-08-13 22:22:43 +02:00
|
|
|
static cl::alias VerboseAlias("v", cl::Optional,
|
2004-08-10 18:26:01 +02:00
|
|
|
cl::desc("Alias for -verbose"), cl::aliasopt(Verbose));
|
|
|
|
|
2004-08-13 22:22:43 +02:00
|
|
|
static cl::opt<bool> Debug("debug", cl::Optional, cl::init(false),
|
|
|
|
cl::Hidden, cl::desc("Print out debugging information"));
|
|
|
|
|
|
|
|
static cl::alias DebugAlias("d", cl::Optional,
|
|
|
|
cl::desc("Alias for -debug"), cl::aliasopt(Debug));
|
|
|
|
|
|
|
|
static cl::opt<bool> TimeActions("time-actions", cl::Optional, cl::init(false),
|
2004-08-10 18:26:01 +02:00
|
|
|
cl::desc("Print execution time for each action taken"));
|
|
|
|
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
//=== ADVANCED OPTIONS
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
|
2004-08-13 22:22:43 +02:00
|
|
|
static cl::opt<std::string> ConfigDir("config-dir", cl::Optional,
|
|
|
|
cl::desc("Specify a configuration directory to override defaults"),
|
|
|
|
cl::value_desc("directory"));
|
2004-08-10 18:26:01 +02:00
|
|
|
|
|
|
|
static cl::opt<bool> EmitRawCode("emit-raw-code", cl::Hidden,
|
|
|
|
cl::desc("Emit raw, unoptimized code"));
|
|
|
|
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
//=== POSITIONAL OPTIONS
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
|
|
|
|
static cl::list<std::string> Files(cl::Positional, cl::OneOrMore,
|
2004-08-13 22:22:43 +02:00
|
|
|
cl::desc("[Sources/objects/libraries]"));
|
|
|
|
|
|
|
|
static cl::list<std::string> Languages("x", cl::ZeroOrMore,
|
|
|
|
cl::desc("Specify the source language for subsequent files"),
|
|
|
|
cl::value_desc("language"));
|
|
|
|
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
//=== GetFileType - determine type of a file
|
|
|
|
//===------------------------------------------------------------------------===
|
|
|
|
const std::string GetFileType(const std::string& fname, unsigned pos ) {
|
|
|
|
static std::vector<std::string>::iterator langIt = Languages.begin();
|
|
|
|
static std::string CurrLang = "";
|
|
|
|
|
|
|
|
// If a -x LANG option has been specified ..
|
|
|
|
if ( langIt != Languages.end() )
|
|
|
|
// If the -x LANG option came before the current file on command line
|
|
|
|
if ( Languages.getPosition( langIt - Languages.begin() ) < pos ) {
|
|
|
|
// use that language
|
|
|
|
CurrLang = *langIt++;
|
|
|
|
return CurrLang;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there's a current language in effect
|
|
|
|
if (!CurrLang.empty())
|
|
|
|
return CurrLang; // use that language
|
|
|
|
|
|
|
|
// otherwise just determine lang from the filename's suffix
|
|
|
|
return fname.substr( fname.rfind('.',fname.size()) + 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
} // end anonymous namespace
|
2004-08-10 18:26:01 +02:00
|
|
|
|
|
|
|
|
|
|
|
/// @brief The main program for llvmc
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
// Make sure we print stack trace if we get bad signals
|
|
|
|
PrintStackTraceOnErrorSignal();
|
|
|
|
|
|
|
|
// Parse the command line options
|
|
|
|
cl::ParseCommandLineOptions(argc, argv,
|
|
|
|
" LLVM Compilation Driver (llvmc)\n\n"
|
|
|
|
" This program provides easy invocation of the LLVM tool set\n"
|
|
|
|
" and source language compiler tools.\n"
|
|
|
|
);
|
|
|
|
|
2004-08-13 22:22:43 +02:00
|
|
|
// Deal with unimplemented options.
|
|
|
|
if (Native)
|
|
|
|
std::cerr << argv[0] << ": Not implemented yet: -native";
|
|
|
|
if (EmitRawCode)
|
|
|
|
std::cerr << argv[0] << ": Not implemented yet: -emit-raw-code";
|
|
|
|
|
|
|
|
// Default the output file, only if we're going to try to link
|
|
|
|
if (OutputFilename.empty() && OptLevel == CompilerDriver::LINKING)
|
|
|
|
OutputFilename = "a.out";
|
|
|
|
|
|
|
|
// Construct the ConfigDataProvider object
|
|
|
|
LLVMC_ConfigDataProvider Provider;
|
2004-08-14 11:37:15 +02:00
|
|
|
Provider.setConfigDir(ConfigDir);
|
2004-08-13 22:22:43 +02:00
|
|
|
|
2004-08-10 18:26:01 +02:00
|
|
|
// Construct the CompilerDriver object
|
2004-08-13 22:22:43 +02:00
|
|
|
CompilerDriver CD(Provider);
|
|
|
|
|
|
|
|
// Configure the driver based on options
|
|
|
|
CD.setVerbose(Verbose);
|
|
|
|
CD.setDebug(Debug);
|
|
|
|
CD.setDryRun(DryRun);
|
|
|
|
CD.setFinalPhase(FinalPhase);
|
|
|
|
CD.setOptimization(OptLevel);
|
|
|
|
CD.setOutputMachine(OutputMachine);
|
|
|
|
CD.setEmitNativeCode(Native);
|
|
|
|
CD.setEmitRawCode(EmitRawCode);
|
|
|
|
std::vector<std::string>::iterator pathIt = LibPaths.begin();
|
|
|
|
while ( pathIt != LibPaths.end() ) {
|
|
|
|
CD.addLibraryPath( *pathIt++ );
|
|
|
|
}
|
2004-08-10 18:26:01 +02:00
|
|
|
|
2004-08-13 22:22:43 +02:00
|
|
|
// Prepare the list of files to be compiled by the CompilerDriver.
|
|
|
|
CompilerDriver::InputList InpList;
|
|
|
|
std::vector<std::string>::iterator fileIt = Files.begin();
|
|
|
|
std::vector<std::string>::iterator libIt = Libraries.begin();
|
|
|
|
unsigned libPos = 0, filePos = 0;
|
|
|
|
while ( 1 ) {
|
|
|
|
if ( libIt != Libraries.end() )
|
|
|
|
libPos = Libraries.getPosition( libIt - Libraries.begin() );
|
|
|
|
else
|
|
|
|
libPos = 0;
|
|
|
|
if ( fileIt != Files.end() )
|
|
|
|
filePos = Files.getPosition( fileIt - Files.begin() );
|
|
|
|
else
|
|
|
|
filePos = 0;
|
|
|
|
|
|
|
|
if ( filePos != 0 && (libPos == 0 || filePos < libPos) ) {
|
|
|
|
// Add a source file
|
|
|
|
InpList.push_back( std::make_pair(*fileIt, GetFileType(*fileIt,filePos)));
|
|
|
|
++fileIt;
|
|
|
|
}
|
|
|
|
else if ( libPos != 0 && (filePos == 0 || libPos < filePos) ) {
|
|
|
|
// Add a library
|
|
|
|
InpList.push_back( std::make_pair(*libIt++,""));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break; // we're done with the list
|
|
|
|
}
|
2004-08-10 18:26:01 +02:00
|
|
|
|
|
|
|
// Tell the driver to do its thing
|
2004-08-13 22:22:43 +02:00
|
|
|
int result = CD.execute(InpList,OutputFilename);
|
2004-08-10 18:26:01 +02:00
|
|
|
if (result != 0) {
|
|
|
|
std::cerr << argv[0] << ": Error executing actions. Terminated.\n";
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// All is good, return success
|
|
|
|
return 0;
|
|
|
|
}
|