mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-26 13:10:42 +00:00
Implement many new features for llvmc. This is the first version that will
actually execute actions and it is been shown to optimize a Stacker program git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15912 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8831db745b
commit
bae6825e1d
@ -14,6 +14,7 @@
|
||||
|
||||
#include "CompilerDriver.h"
|
||||
#include "ConfigLexer.h"
|
||||
#include "Support/SystemUtils.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace llvm;
|
||||
@ -33,27 +34,25 @@ namespace {
|
||||
|
||||
const char OutputSuffix[] = ".o";
|
||||
|
||||
void WriteAction(CompilerDriver::Action* a ) {
|
||||
std::cerr << a->program;
|
||||
std::vector<std::string>::iterator I = a->args.begin();
|
||||
while (I != a->args.end()) {
|
||||
void WriteAction(CompilerDriver::Action* action ) {
|
||||
std::cerr << action->program;
|
||||
std::vector<std::string>::iterator I = action->args.begin();
|
||||
while (I != action->args.end()) {
|
||||
std::cerr << " " + *I;
|
||||
++I;
|
||||
}
|
||||
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()) {
|
||||
void DumpAction(CompilerDriver::Action* action) {
|
||||
std::cerr << "command = " << action->program;
|
||||
std::vector<std::string>::iterator I = action->args.begin();
|
||||
while (I != action->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";
|
||||
std::cerr << "flags = " << action->flags << "\n";
|
||||
}
|
||||
|
||||
void DumpConfigData(CompilerDriver::ConfigData* cd, const std::string& type ){
|
||||
@ -79,11 +78,57 @@ namespace {
|
||||
/// This specifies the passes to run for OPT_FAST_COMPILE (-O1)
|
||||
/// which should reduce the volume of code and make compilation
|
||||
/// faster. This is also safe on any llvm module.
|
||||
static const char* DefaultOptimizations[] = {
|
||||
"-simplifycfg", "-mem2reg", "-mergereturn", "-instcombine",
|
||||
static const char* DefaultFastCompileOptimizations[] = {
|
||||
"-simplifycfg", "-mem2reg", "-instcombine"
|
||||
};
|
||||
}
|
||||
|
||||
// Stuff in this namespace properly belongs in lib/System and needs
|
||||
// to be portable but we're avoiding that for now.
|
||||
namespace sys {
|
||||
std::string MakeTemporaryDirectory() {
|
||||
char temp_name[64];
|
||||
strcpy(temp_name,"/tmp/llvm_XXXXXX");
|
||||
if (0 == mkdtemp(temp_name))
|
||||
throw std::string("Can't create temporary directory");
|
||||
return temp_name;
|
||||
}
|
||||
|
||||
std::string FindExecutableInPath(const std::string& program) {
|
||||
// First, just see if the program is already executable
|
||||
if (isExecutableFile(program)) return program;
|
||||
|
||||
// Get the path. If its empty, we can't do anything
|
||||
const char *PathStr = getenv("PATH");
|
||||
if (PathStr == 0) return "";
|
||||
|
||||
// Now we have a colon separated list of directories to search; try them.
|
||||
unsigned PathLen = strlen(PathStr);
|
||||
while (PathLen) {
|
||||
// Find the first colon...
|
||||
const char *Colon = std::find(PathStr, PathStr+PathLen, ':');
|
||||
|
||||
// Check to see if this first directory contains the executable...
|
||||
std::string FilePath = std::string(PathStr, Colon) + '/' + program;
|
||||
if (isExecutableFile(FilePath))
|
||||
return FilePath; // Found the executable!
|
||||
|
||||
// Nope it wasn't in this directory, check the next range!
|
||||
PathLen -= Colon-PathStr;
|
||||
PathStr = Colon;
|
||||
|
||||
// Advance past duplicate coons
|
||||
while (*PathStr == ':') {
|
||||
PathStr++;
|
||||
PathLen--;
|
||||
}
|
||||
}
|
||||
|
||||
// If we fell out, we ran out of directories in PATH to search, return failure
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
CompilerDriver::CompilerDriver(ConfigDataProvider& confDatProv )
|
||||
: cdp(&confDatProv)
|
||||
, finalPhase(LINKING)
|
||||
@ -94,54 +139,53 @@ CompilerDriver::CompilerDriver(ConfigDataProvider& confDatProv )
|
||||
, timeActions(false)
|
||||
, emitRawCode(false)
|
||||
, emitNativeCode(false)
|
||||
, keepTemps(false)
|
||||
, machine()
|
||||
, LibraryPaths()
|
||||
, PreprocessorOptions()
|
||||
, TranslatorOptions()
|
||||
, OptimizerOptions()
|
||||
, AssemblerOptions()
|
||||
, LinkerOptions()
|
||||
, AdditionalArgs()
|
||||
, TempDir()
|
||||
{
|
||||
// FIXME: These libraries are platform specific
|
||||
LibraryPaths.push_back("/lib");
|
||||
LibraryPaths.push_back("/usr/lib");
|
||||
AdditionalArgs.reserve(NUM_PHASES);
|
||||
StringVector emptyVec;
|
||||
for (unsigned i = 0; i < NUM_PHASES; ++i)
|
||||
AdditionalArgs.push_back(emptyVec);
|
||||
}
|
||||
|
||||
CompilerDriver::~CompilerDriver() {
|
||||
cdp = 0;
|
||||
LibraryPaths.clear();
|
||||
PreprocessorOptions.clear();
|
||||
TranslatorOptions.clear();
|
||||
OptimizerOptions.clear();
|
||||
AssemblerOptions.clear();
|
||||
LinkerOptions.clear();
|
||||
AdditionalArgs.clear();
|
||||
}
|
||||
|
||||
CompilerDriver::ConfigData::ConfigData()
|
||||
: langName()
|
||||
, PreProcessor()
|
||||
, Translator()
|
||||
, Optimizer()
|
||||
, Assembler()
|
||||
, Linker()
|
||||
{
|
||||
StringVector emptyVec;
|
||||
for (unsigned i = 0; i < NUM_PHASES; ++i)
|
||||
opts.push_back(emptyVec);
|
||||
}
|
||||
|
||||
void CompilerDriver::error( const std::string& errmsg ) {
|
||||
std::cerr << "Error: " << errmsg << ".\n";
|
||||
std::cerr << "llvmc: Error: " << errmsg << ".\n";
|
||||
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;
|
||||
Action* pat = 0; ///< The pattern/template for the action
|
||||
Action* action = new Action; ///< The actual action to execute
|
||||
|
||||
// Get the action pattern
|
||||
switch (phase) {
|
||||
case PREPROCESSING: pat = &cd->PreProcessor; break;
|
||||
@ -155,74 +199,93 @@ CompilerDriver::Action* CompilerDriver::GetAction(ConfigData* cd,
|
||||
}
|
||||
assert(pat != 0 && "Invalid command pattern");
|
||||
|
||||
// Create the resulting action
|
||||
Action* a = new Action(*pat);
|
||||
// Copy over some pattern things that don't need to change
|
||||
action->program = pat->program;
|
||||
action->flags = pat->flags;
|
||||
|
||||
// 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;
|
||||
// Do the substitutions from the pattern to the actual
|
||||
StringVector::iterator PI = pat->args.begin();
|
||||
StringVector::iterator PE = pat->args.end();
|
||||
while (PI != PE) {
|
||||
if ((*PI)[0] == '@') {
|
||||
if (*PI == "@in@") {
|
||||
action->args.push_back(input);
|
||||
} else if (*PI == "@out@") {
|
||||
action->args.push_back(output);
|
||||
} else if (*PI == "@time@") {
|
||||
if (timePasses)
|
||||
action->args.push_back("-time-passes");
|
||||
} else if (*PI == "@stats@") {
|
||||
if (showStats)
|
||||
action->args.push_back("-stats");
|
||||
} else if (*PI == "@target@") {
|
||||
// FIXME: Ignore for now
|
||||
} else if (*PI == "@opt@") {
|
||||
if (!emitRawCode) {
|
||||
if (pat->isSet(GROKS_DASH_O)) {
|
||||
if (optLevel != OPT_NONE) {
|
||||
std::string optArg("-O");
|
||||
switch (optLevel) {
|
||||
case OPT_FAST_COMPILE : optArg.append("1"); break;
|
||||
case OPT_SIMPLE: optArg.append("2"); break;
|
||||
case OPT_AGGRESSIVE: optArg.append("3"); break;
|
||||
case OPT_LINK_TIME: optArg.append("4"); break;
|
||||
case OPT_AGGRESSIVE_LINK_TIME: optArg.append("5"); break;
|
||||
default :
|
||||
assert(!"Invalid optimization argument!");
|
||||
optArg.append("0");
|
||||
break;
|
||||
}
|
||||
action->args.push_back(optArg);
|
||||
}
|
||||
} else {
|
||||
if (cd->opts.size() > static_cast<unsigned>(optLevel) &&
|
||||
!cd->opts[optLevel].empty())
|
||||
action->args.insert(action->args.end(), cd->opts[optLevel].begin(),
|
||||
cd->opts[optLevel].end());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error("Invalid substitution name");
|
||||
}
|
||||
} else {
|
||||
// Its not a substitution, just put it in the action
|
||||
action->args.push_back(*PI);
|
||||
}
|
||||
PI++;
|
||||
}
|
||||
return a;
|
||||
|
||||
// Get specific options for each kind of action type
|
||||
StringVector& args = AdditionalArgs[phase];
|
||||
|
||||
// Add specific options for each kind of action type
|
||||
action->args.insert(action->args.end(), args.begin(), args.end());
|
||||
|
||||
// Finally, we're done
|
||||
return action;
|
||||
}
|
||||
|
||||
void CompilerDriver::DoAction(Action*a)
|
||||
{
|
||||
bool CompilerDriver::DoAction(Action*action) {
|
||||
assert(action != 0 && "Invalid Action!");
|
||||
if (isVerbose)
|
||||
WriteAction(a);
|
||||
WriteAction(action);
|
||||
if (!isDryRun) {
|
||||
std::cerr << "execve(\"" << a->program << "\",[\"";
|
||||
std::vector<std::string>::iterator I = a->args.begin();
|
||||
while (I != a->args.end()) {
|
||||
std::cerr << *I;
|
||||
++I;
|
||||
if (I != a->args.end())
|
||||
std::cerr << "\",\"";
|
||||
}
|
||||
std::cerr << "\"],ENV);\n";
|
||||
std::string prog(sys::FindExecutableInPath(action->program));
|
||||
if (prog.empty())
|
||||
error("Can't find program '" + action->program + "'");
|
||||
|
||||
// Get the program's arguments
|
||||
const char* argv[action->args.size() + 1];
|
||||
argv[0] = prog.c_str();
|
||||
unsigned i = 1;
|
||||
for (; i <= action->args.size(); ++i)
|
||||
argv[i] = action->args[i-1].c_str();
|
||||
argv[i] = 0;
|
||||
|
||||
// Invoke the program
|
||||
return !ExecWait(argv, environ);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int CompilerDriver::execute(const InputList& InpList,
|
||||
@ -259,15 +322,11 @@ int CompilerDriver::execute(const InputList& InpList,
|
||||
std::vector<Action*> actions;
|
||||
|
||||
// Create a temporary directory for our temporary files
|
||||
char temp_name[64];
|
||||
strcpy(temp_name,"/tmp/llvm_XXXXXX");
|
||||
if (0 == mkdtemp(temp_name))
|
||||
error("Can't create temporary directory");
|
||||
std::string TempDir(temp_name);
|
||||
std::string TempPreprocessorOut(TempDir + "/preproc.tmp");
|
||||
std::string TempTranslatorOut(TempDir + "/trans.tmp");
|
||||
std::string TempOptimizerOut(TempDir + "/opt.tmp");
|
||||
std::string TempAssemblerOut(TempDir + "/asm.tmp");
|
||||
std::string TempDir(sys::MakeTemporaryDirectory());
|
||||
std::string TempPreprocessorOut(TempDir + "/preproc.o");
|
||||
std::string TempTranslatorOut(TempDir + "/trans.o");
|
||||
std::string TempOptimizerOut(TempDir + "/opt.o");
|
||||
std::string TempAssemblerOut(TempDir + "/asm.o");
|
||||
|
||||
/// PRE-PROCESSING / TRANSLATION / OPTIMIZATION / ASSEMBLY phases
|
||||
// for each input item
|
||||
@ -312,76 +371,137 @@ int CompilerDriver::execute(const InputList& InpList,
|
||||
OutFile = Output;
|
||||
}
|
||||
|
||||
// Initialize the input file
|
||||
std::string InFile(I->first);
|
||||
|
||||
// PRE-PROCESSING PHASE
|
||||
Action& a = cd->PreProcessor;
|
||||
Action& action = cd->PreProcessor;
|
||||
|
||||
// Get the preprocessing action, if needed, or error if appropriate
|
||||
if (!a.program.empty()) {
|
||||
if (a.isSet(REQUIRED_FLAG) || finalPhase == PREPROCESSING) {
|
||||
actions.push_back(GetAction(cd,I->first,
|
||||
TempPreprocessorOut,PREPROCESSING));
|
||||
if (!action.program.empty()) {
|
||||
if (action.isSet(REQUIRED_FLAG) || finalPhase == PREPROCESSING) {
|
||||
if (finalPhase == PREPROCESSING)
|
||||
actions.push_back(GetAction(cd,InFile,OutFile,PREPROCESSING));
|
||||
else {
|
||||
actions.push_back(GetAction(cd,InFile,TempPreprocessorOut,
|
||||
PREPROCESSING));
|
||||
InFile = TempPreprocessorOut;
|
||||
}
|
||||
}
|
||||
} else if (finalPhase == PREPROCESSING) {
|
||||
error(cd->langName + " does not support pre-processing");
|
||||
} else if (a.isSet(REQUIRED_FLAG)) {
|
||||
} else if (action.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
|
||||
a = cd->Translator;
|
||||
action = cd->Translator;
|
||||
|
||||
// Get the translation action, if needed, or error if appropriate
|
||||
if (!a.program.empty()) {
|
||||
if (a.isSet(REQUIRED_FLAG) || finalPhase == TRANSLATION) {
|
||||
actions.push_back(GetAction(cd,I->first,TempTranslatorOut,TRANSLATION));
|
||||
if (!action.program.empty()) {
|
||||
if (action.isSet(REQUIRED_FLAG) || finalPhase == TRANSLATION) {
|
||||
if (finalPhase == TRANSLATION)
|
||||
actions.push_back(GetAction(cd,InFile,OutFile,TRANSLATION));
|
||||
else {
|
||||
actions.push_back(GetAction(cd,InFile,TempTranslatorOut,TRANSLATION));
|
||||
InFile = TempTranslatorOut;
|
||||
}
|
||||
|
||||
// ll -> bc Helper
|
||||
if (action.isSet(OUTPUT_IS_ASM_FLAG)) {
|
||||
/// The output of the translator is an LLVM Assembly program
|
||||
/// We need to translate it to bytecode
|
||||
Action* action = new Action();
|
||||
action->program = "llvm-as";
|
||||
action->args.push_back(InFile);
|
||||
action->args.push_back("-o");
|
||||
InFile += ".bc";
|
||||
action->args.push_back(InFile);
|
||||
actions.push_back(action);
|
||||
}
|
||||
}
|
||||
} else if (finalPhase == TRANSLATION) {
|
||||
error(cd->langName + " does not support translation");
|
||||
} else if (a.isSet(REQUIRED_FLAG)) {
|
||||
} else if (action.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
|
||||
a = cd->Optimizer;
|
||||
action = cd->Optimizer;
|
||||
|
||||
// Get the optimization action, if needed, or error if appropriate
|
||||
if (!a.program.empty()) {
|
||||
actions.push_back(GetAction(cd,I->first,TempOptimizerOut,OPTIMIZATION));
|
||||
if (!action.program.empty() && !emitRawCode) {
|
||||
if (action.isSet(REQUIRED_FLAG) || finalPhase == OPTIMIZATION) {
|
||||
if (finalPhase == OPTIMIZATION)
|
||||
actions.push_back(GetAction(cd,InFile,OutFile,OPTIMIZATION));
|
||||
else {
|
||||
actions.push_back(GetAction(cd,InFile,TempOptimizerOut,OPTIMIZATION));
|
||||
InFile = TempOptimizerOut;
|
||||
}
|
||||
// ll -> bc Helper
|
||||
if (action.isSet(OUTPUT_IS_ASM_FLAG)) {
|
||||
/// The output of the translator is an LLVM Assembly program
|
||||
/// We need to translate it to bytecode
|
||||
Action* action = new Action();
|
||||
action->program = "llvm-as";
|
||||
action->args.push_back(InFile);
|
||||
action->args.push_back("-o");
|
||||
InFile += ".bc";
|
||||
action->args.push_back(InFile);
|
||||
actions.push_back(action);
|
||||
}
|
||||
}
|
||||
} else if (finalPhase == OPTIMIZATION) {
|
||||
error(cd->langName + " does not support optimization");
|
||||
} else if (a.isSet(REQUIRED_FLAG)) {
|
||||
} else if (action.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; }
|
||||
|
||||
/// ASSEMBLY PHASE
|
||||
if (emitNativeCode) {
|
||||
// We must cause native code to be generated
|
||||
} else {
|
||||
}
|
||||
|
||||
// Go to next file to be processed
|
||||
++I;
|
||||
}
|
||||
|
||||
/// LINKING PHASE
|
||||
if (emitNativeCode) {
|
||||
} else {
|
||||
}
|
||||
|
||||
/// RUN THE ACTIONS
|
||||
std::vector<Action*>::iterator aIter = actions.begin();
|
||||
while (aIter != actions.end()) {
|
||||
DoAction(*aIter);
|
||||
if (!DoAction(*aIter))
|
||||
error("Action failed");
|
||||
aIter++;
|
||||
}
|
||||
|
||||
// Cleanup files
|
||||
CleanupTempFile(TempPreprocessorOut.c_str());
|
||||
CleanupTempFile(TempTranslatorOut.c_str());
|
||||
CleanupTempFile(TempOptimizerOut.c_str());
|
||||
if (!keepTemps) {
|
||||
// Cleanup files
|
||||
CleanupTempFile(TempPreprocessorOut.c_str());
|
||||
CleanupTempFile(TempTranslatorOut.c_str());
|
||||
CleanupTempFile(TempOptimizerOut.c_str());
|
||||
|
||||
// Cleanup temporary directory we created
|
||||
if (0 == access(TempDir.c_str(), F_OK | W_OK))
|
||||
rmdir(TempDir.c_str());
|
||||
// Cleanup temporary directory we created
|
||||
if (0 == access(TempDir.c_str(), F_OK | W_OK))
|
||||
rmdir(TempDir.c_str());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -32,13 +32,17 @@ namespace llvm {
|
||||
/// @brief A vector of strings, commonly used
|
||||
typedef std::vector<std::string> StringVector;
|
||||
|
||||
/// @brief A table of strings, indexed typically by Phases
|
||||
typedef std::vector<StringVector> StringTable;
|
||||
|
||||
/// @brief The phases of processing that llvmc understands
|
||||
enum Phases {
|
||||
PREPROCESSING, ///< Source language combining, filtering, substitution
|
||||
TRANSLATION, ///< Translate source -> LLVM bytecode/assembly
|
||||
OPTIMIZATION, ///< Optimize translation result
|
||||
LINKING, ///< Link bytecode and native code
|
||||
ASSEMBLY, ///< Convert program to executable
|
||||
LINKING, ///< Link bytecode and native code
|
||||
NUM_PHASES ///< Always last!
|
||||
};
|
||||
|
||||
/// @brief The levels of optimization llvmc understands
|
||||
@ -56,9 +60,10 @@ namespace llvm {
|
||||
REQUIRED_FLAG = 0x0001, ///< Should the action always be run?
|
||||
GROKS_DASH_O_FLAG = 0x0002, ///< Understands the -On options?
|
||||
PREPROCESSES_FLAG = 0x0004, ///< Does this action preprocess?
|
||||
OPTIMIZES_FLAG = 0x0008, ///< Does this action optimize?
|
||||
GROKS_O10N_FLAG = 0x0010, ///< Understands optimization options?
|
||||
FLAGS_MASK = 0x001F, ///< Union of all flags
|
||||
TRANSLATES_FLAG = 0x0008, ///< Does this action translate?
|
||||
OPTIMIZES_FLAG = 0x0010, ///< Does this action optimize?
|
||||
OUTPUT_IS_ASM_FLAG = 0x0020, ///< Action produces .ll files?
|
||||
FLAGS_MASK = 0x003F, ///< Union of all flags
|
||||
};
|
||||
|
||||
/// This type is the input list to the CompilerDriver. It provides
|
||||
@ -73,25 +78,24 @@ namespace llvm {
|
||||
/// @brief A structure to hold the action data for a given source
|
||||
/// language.
|
||||
struct Action {
|
||||
Action() : inputAt(0) , outputAt(0), flags(0) {}
|
||||
Action() : flags(0) {}
|
||||
std::string program; ///< The program to execve
|
||||
StringVector args; ///< Arguments to the program
|
||||
size_t inputAt; ///< Argument index to insert input file
|
||||
size_t outputAt; ///< Argument index to insert output file
|
||||
unsigned flags; ///< Action specific flags
|
||||
void set(unsigned fl ) { flags |= fl; }
|
||||
void clear(unsigned fl) { flags &= (FLAGS_MASK ^ fl); }
|
||||
bool isSet(unsigned fl) { return flags&fl != 0; }
|
||||
bool isSet(unsigned fl) { return (flags&fl) != 0; }
|
||||
};
|
||||
|
||||
struct ConfigData {
|
||||
std::string langName; ///< The name of the source language
|
||||
std::vector<StringVector> opts; ///< The o10n options for each level
|
||||
Action PreProcessor; ///< PreProcessor command line
|
||||
Action Translator; ///< Translator command line
|
||||
Action Optimizer; ///< Optimizer command line
|
||||
Action Assembler; ///< Assembler command line
|
||||
Action Linker; ///< Linker command line
|
||||
ConfigData();
|
||||
std::string langName; ///< The name of the source language
|
||||
StringTable opts; ///< The o10n options for each level
|
||||
Action PreProcessor; ///< PreProcessor command line
|
||||
Action Translator; ///< Translator command line
|
||||
Action Optimizer; ///< Optimizer command line
|
||||
Action Assembler; ///< Assembler command line
|
||||
Action Linker; ///< Linker command line
|
||||
};
|
||||
|
||||
/// This pure virtual interface class defines the interface between the
|
||||
@ -148,6 +152,12 @@ namespace llvm {
|
||||
/// execution time of each action taken.
|
||||
void setTimeActions( bool TF ) { timeActions = TF; }
|
||||
|
||||
/// @brief Cause the CompilerDriver to print timings for each pass.
|
||||
void setTimePasses( bool TF ) { timePasses = TF; }
|
||||
|
||||
/// @brief Cause the CompilerDriver to show statistics gathered
|
||||
void setShowStats( bool TF ) { showStats = TF; }
|
||||
|
||||
/// @brief Indicate that native code is to be generated instead
|
||||
/// of LLVM bytecode.
|
||||
void setEmitNativeCode( bool TF ) { emitNativeCode = TF; }
|
||||
@ -155,34 +165,17 @@ namespace llvm {
|
||||
/// @brief Indicate that raw, unoptimized code is to be generated.
|
||||
void setEmitRawCode(bool TF ) { emitRawCode = TF; }
|
||||
|
||||
void setKeepTemporaries(bool TF) { keepTemps = TF; }
|
||||
|
||||
/// @brief Set the output machine name.
|
||||
void setOutputMachine( const std::string& machineName ) {
|
||||
machine = machineName;
|
||||
}
|
||||
|
||||
/// @brief Set Preprocessor specific options
|
||||
void setPreprocessorOptions(const std::vector<std::string>& opts) {
|
||||
PreprocessorOptions = opts;
|
||||
}
|
||||
|
||||
/// @brief Set Translator specific options
|
||||
void setTranslatorOptions(const std::vector<std::string>& opts) {
|
||||
TranslatorOptions = opts;
|
||||
}
|
||||
|
||||
/// @brief Set Optimizer specific options
|
||||
void setOptimizerOptions(const std::vector<std::string>& opts) {
|
||||
OptimizerOptions = opts;
|
||||
}
|
||||
|
||||
/// @brief Set Assembler specific options
|
||||
void setAssemblerOptions(const std::vector<std::string>& opts) {
|
||||
AssemblerOptions = opts;
|
||||
}
|
||||
|
||||
/// @brief Set Linker specific options
|
||||
void setLinkerOptions(const std::vector<std::string>& opts) {
|
||||
LinkerOptions = opts;
|
||||
void setPhaseArgs(Phases phase, const std::vector<std::string>& opts) {
|
||||
assert(phase <= LINKING && phase >= PREPROCESSING);
|
||||
AdditionalArgs[phase] = opts;
|
||||
}
|
||||
|
||||
/// @brief Set Library Paths
|
||||
@ -202,7 +195,7 @@ namespace llvm {
|
||||
private:
|
||||
Action* GetAction(ConfigData* cd, const std::string& input,
|
||||
const std::string& output, Phases phase );
|
||||
void DoAction(Action* a);
|
||||
bool DoAction(Action* a);
|
||||
|
||||
/// @}
|
||||
/// @name Data
|
||||
@ -215,15 +208,15 @@ namespace llvm {
|
||||
bool isVerbose; ///< Print actions?
|
||||
bool isDebug; ///< Print lotsa debug info?
|
||||
bool timeActions; ///< Time the actions executed ?
|
||||
bool timePasses; ///< Time each pass and print timing ?
|
||||
bool showStats; ///< Show gathered statistics ?
|
||||
bool emitRawCode; ///< Emit Raw (unoptimized) code?
|
||||
bool emitNativeCode; ///< Emit native code instead of bytecode?
|
||||
bool keepTemps; ///< Keep temporary files?
|
||||
std::string machine; ///< Target machine name
|
||||
std::vector<std::string> LibraryPaths;
|
||||
std::vector<std::string> PreprocessorOptions;
|
||||
std::vector<std::string> TranslatorOptions;
|
||||
std::vector<std::string> OptimizerOptions;
|
||||
std::vector<std::string> AssemblerOptions;
|
||||
std::vector<std::string> LinkerOptions;
|
||||
StringVector LibraryPaths; ///< -L options
|
||||
StringTable AdditionalArgs; ///< The -Txyz options
|
||||
std::string TempDir; ///< Name of the temporary directory.
|
||||
|
||||
/// @}
|
||||
|
||||
|
@ -15,21 +15,21 @@
|
||||
#include "ConfigData.h"
|
||||
#include "ConfigLexer.h"
|
||||
#include "CompilerDriver.h"
|
||||
#include "Support/CommandLine.h"
|
||||
#include "Support/StringExtras.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
extern int ::Configlineno;
|
||||
|
||||
namespace llvm {
|
||||
ConfigLexerInfo ConfigLexerData;
|
||||
ConfigLexerInfo ConfigLexerState;
|
||||
InputProvider* ConfigLexerInput = 0;
|
||||
|
||||
InputProvider::~InputProvider() {}
|
||||
void InputProvider::error(const std::string& msg) {
|
||||
std::cerr << name << ":" << Configlineno << ": Error: " << msg << "\n";
|
||||
std::cerr << name << ":" << ConfigLexerState.lineNum << ": Error: " <<
|
||||
msg << "\n";
|
||||
errCount++;
|
||||
}
|
||||
|
||||
@ -65,17 +65,34 @@ namespace {
|
||||
std::ifstream F;
|
||||
};
|
||||
|
||||
cl::opt<bool> DumpTokens("dump-tokens", cl::Optional, cl::Hidden, cl::init(false),
|
||||
cl::desc("Dump lexical tokens (debug use only)."));
|
||||
|
||||
struct Parser
|
||||
{
|
||||
Parser() {
|
||||
token = EOFTOK;
|
||||
provider = 0;
|
||||
confDat = 0;
|
||||
ConfigLexerState.lineNum = 1;
|
||||
ConfigLexerState.in_value = false;
|
||||
ConfigLexerState.StringVal.clear();
|
||||
ConfigLexerState.IntegerVal = 0;
|
||||
};
|
||||
|
||||
ConfigLexerTokens token;
|
||||
InputProvider* provider;
|
||||
CompilerDriver::ConfigData* confDat;
|
||||
CompilerDriver::Action* action;
|
||||
|
||||
int next() { return token = Configlex(); }
|
||||
int next() {
|
||||
token = Configlex();
|
||||
if (DumpTokens)
|
||||
std::cerr << token << "\n";
|
||||
return token;
|
||||
}
|
||||
|
||||
bool next_is_real() {
|
||||
token = Configlex();
|
||||
next();
|
||||
return (token != EOLTOK) && (token != ERRORTOK) && (token != 0);
|
||||
}
|
||||
|
||||
@ -96,7 +113,7 @@ namespace {
|
||||
switch (token ) {
|
||||
case STRING :
|
||||
case OPTION :
|
||||
result += ConfigLexerData.StringVal + " ";
|
||||
result += ConfigLexerState.StringVal + " ";
|
||||
break;
|
||||
default:
|
||||
error("Invalid name");
|
||||
@ -130,15 +147,32 @@ namespace {
|
||||
return result;
|
||||
}
|
||||
|
||||
void parseOptionList(CompilerDriver::StringVector& optList ) {
|
||||
while (next_is_real()) {
|
||||
if (token == STRING || token == OPTION)
|
||||
optList.push_back(ConfigLexerData.StringVal);
|
||||
else {
|
||||
error("Expecting a program option", false);
|
||||
break;
|
||||
}
|
||||
bool parseSubstitution(CompilerDriver::StringVector& optList) {
|
||||
switch (token) {
|
||||
case IN_SUBST: optList.push_back("@in@"); break;
|
||||
case OUT_SUBST: optList.push_back("@out@"); break;
|
||||
case TIME_SUBST: optList.push_back("@time@"); break;
|
||||
case STATS_SUBST: optList.push_back("@stats@"); break;
|
||||
case OPT_SUBST: optList.push_back("@opt@"); break;
|
||||
case TARGET_SUBST: optList.push_back("@target@"); break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void parseOptionList(CompilerDriver::StringVector& optList ) {
|
||||
if (next() == EQUALS) {
|
||||
while (next_is_real()) {
|
||||
if (token == STRING || token == OPTION)
|
||||
optList.push_back(ConfigLexerState.StringVal);
|
||||
else if (!parseSubstitution(optList)) {
|
||||
error("Expecting a program argument or substitution", false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
error("Expecting '='");
|
||||
}
|
||||
|
||||
void parseLang() {
|
||||
@ -174,25 +208,17 @@ namespace {
|
||||
// no value (valid)
|
||||
action.program.clear();
|
||||
action.args.clear();
|
||||
action.inputAt = 0;
|
||||
action.outputAt = 0;
|
||||
} else {
|
||||
if (token == STRING || token == OPTION) {
|
||||
action.program = ConfigLexerData.StringVal;
|
||||
action.program = ConfigLexerState.StringVal;
|
||||
} else {
|
||||
error("Expecting a program name");
|
||||
}
|
||||
while (next_is_real()) {
|
||||
if (token == STRING || token == OPTION) {
|
||||
action.args.push_back(ConfigLexerData.StringVal);
|
||||
} else if (token == IN_SUBST) {
|
||||
action.inputAt = action.args.size();
|
||||
action.args.push_back("@in@");
|
||||
} else if (token == OUT_SUBST) {
|
||||
action.outputAt = action.args.size();
|
||||
action.args.push_back("@out@");
|
||||
} else {
|
||||
error("Expecting a program argument", false);
|
||||
action.args.push_back(ConfigLexerState.StringVal);
|
||||
} else if (!parseSubstitution(action.args)) {
|
||||
error("Expecting a program argument or substitution", false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -246,12 +272,13 @@ namespace {
|
||||
else
|
||||
confDat->Translator.clear(CompilerDriver::GROKS_DASH_O_FLAG);
|
||||
break;
|
||||
case GROKS_O10N:
|
||||
case OUTPUT_IS_ASM:
|
||||
if (parseBoolean())
|
||||
confDat->Translator.set(CompilerDriver::GROKS_O10N_FLAG);
|
||||
confDat->Translator.set(CompilerDriver::OUTPUT_IS_ASM_FLAG);
|
||||
else
|
||||
confDat->Translator.clear(CompilerDriver::GROKS_O10N_FLAG);
|
||||
confDat->Translator.clear(CompilerDriver::OUTPUT_IS_ASM_FLAG);
|
||||
break;
|
||||
|
||||
default:
|
||||
error("Expecting 'command', 'required', 'preprocesses', "
|
||||
"'groks_dash_O' or 'optimizes'");
|
||||
@ -264,17 +291,29 @@ namespace {
|
||||
case COMMAND:
|
||||
parseCommand(confDat->Optimizer);
|
||||
break;
|
||||
case PREPROCESSES:
|
||||
if (parseBoolean())
|
||||
confDat->Optimizer.set(CompilerDriver::PREPROCESSES_FLAG);
|
||||
else
|
||||
confDat->Optimizer.clear(CompilerDriver::PREPROCESSES_FLAG);
|
||||
break;
|
||||
case TRANSLATES:
|
||||
if (parseBoolean())
|
||||
confDat->Optimizer.set(CompilerDriver::TRANSLATES_FLAG);
|
||||
else
|
||||
confDat->Optimizer.clear(CompilerDriver::TRANSLATES_FLAG);
|
||||
break;
|
||||
case GROKS_DASH_O:
|
||||
if (parseBoolean())
|
||||
confDat->Optimizer.set(CompilerDriver::GROKS_DASH_O_FLAG);
|
||||
else
|
||||
confDat->Optimizer.clear(CompilerDriver::GROKS_DASH_O_FLAG);
|
||||
break;
|
||||
case GROKS_O10N:
|
||||
case OUTPUT_IS_ASM:
|
||||
if (parseBoolean())
|
||||
confDat->Optimizer.set(CompilerDriver::GROKS_O10N_FLAG);
|
||||
confDat->Translator.set(CompilerDriver::OUTPUT_IS_ASM_FLAG);
|
||||
else
|
||||
confDat->Optimizer.clear(CompilerDriver::GROKS_O10N_FLAG);
|
||||
confDat->Translator.clear(CompilerDriver::OUTPUT_IS_ASM_FLAG);
|
||||
break;
|
||||
default:
|
||||
error("Expecting 'command' or 'groks_dash_O'");
|
||||
@ -304,12 +343,6 @@ namespace {
|
||||
else
|
||||
confDat->Linker.clear(CompilerDriver::GROKS_DASH_O_FLAG);
|
||||
break;
|
||||
case GROKS_O10N:
|
||||
if (parseBoolean())
|
||||
confDat->Linker.set(CompilerDriver::GROKS_O10N_FLAG);
|
||||
else
|
||||
confDat->Linker.clear(CompilerDriver::GROKS_O10N_FLAG);
|
||||
break;
|
||||
default:
|
||||
error("Expecting 'command'");
|
||||
break;
|
||||
@ -349,7 +382,6 @@ namespace {
|
||||
p.token = EOFTOK;
|
||||
p.provider = &provider;
|
||||
p.confDat = &confDat;
|
||||
p.action = 0;
|
||||
p.parseFile();
|
||||
}
|
||||
}
|
||||
|
@ -22,9 +22,11 @@ struct ConfigLexerInfo
|
||||
{
|
||||
int64_t IntegerVal;
|
||||
std::string StringVal;
|
||||
bool in_value;
|
||||
unsigned lineNum;
|
||||
};
|
||||
|
||||
extern ConfigLexerInfo ConfigLexerData;
|
||||
extern ConfigLexerInfo ConfigLexerState;
|
||||
|
||||
class InputProvider {
|
||||
public:
|
||||
@ -57,6 +59,10 @@ enum ConfigLexerTokens {
|
||||
STRING, ///< A quoted string
|
||||
IN_SUBST, ///< The input substitution item @in@
|
||||
OUT_SUBST, ///< The output substitution item @out@
|
||||
STATS_SUBST, ///< The stats substitution item @stats@
|
||||
TIME_SUBST, ///< The substitution item @time@
|
||||
OPT_SUBST, ///< The substitution item @opt@
|
||||
TARGET_SUBST, ///< The substitition item @target@
|
||||
LANG, ///< The item "lang" (and case variants)
|
||||
PREPROCESSOR, ///< The item "preprocessor" (and case variants)
|
||||
TRANSLATOR, ///< The item "translator" (and case variants)
|
||||
@ -67,9 +73,10 @@ enum ConfigLexerTokens {
|
||||
REQUIRED, ///< The item "required" (and case variants)
|
||||
COMMAND, ///< The item "command" (and case variants)
|
||||
PREPROCESSES, ///< The item "preprocesses" (and case variants)
|
||||
GROKS_DASH_O, ///< The item "groks_dash_O" (and case variants)
|
||||
GROKS_O10N, ///< The item "groks_optimization" (and case variants)
|
||||
TRANSLATES, ///< The item "translates" (and case variants)
|
||||
OPTIMIZES, ///< The item "optimizes" (and case variants)
|
||||
GROKS_DASH_O, ///< The item "groks_dash_O" (and case variants)
|
||||
OUTPUT_IS_ASM,///< The item "outut_is_asm" (and case variants)
|
||||
OPT1, ///< The item "opt1" (and case variants)
|
||||
OPT2, ///< The item "opt2" (and case variants)
|
||||
OPT3, ///< The item "opt3" (and case variants)
|
||||
|
@ -14,7 +14,6 @@
|
||||
|
||||
|
||||
%option prefix="Config"
|
||||
%option yylineno
|
||||
%option nostdinit
|
||||
%option never-interactive
|
||||
%option batch
|
||||
@ -23,9 +22,9 @@
|
||||
%option 8bit
|
||||
%option outfile="ConfigLexer.cpp"
|
||||
%option ecs
|
||||
%option noreject
|
||||
%option noyymore
|
||||
%array
|
||||
%option noreject
|
||||
%pointer
|
||||
|
||||
%{
|
||||
|
||||
@ -38,53 +37,73 @@
|
||||
if (result == 0 ) result = YY_NULL; \
|
||||
}
|
||||
|
||||
#define YY_FATAL_ERROR(msg) \
|
||||
{ \
|
||||
assert(ConfigLexerInput != 0 && "Oops"); \
|
||||
ConfigLexerInput->error(msg); \
|
||||
}
|
||||
|
||||
#define YY_DECL ConfigLexerTokens llvm::Configlex()
|
||||
|
||||
#define yyterminate() { return EOFTOK; }
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
/* Conversion of text ints to binary */
|
||||
static int64_t IntToVal(const char *Buffer) {
|
||||
int64_t Result = 0;
|
||||
for (; *Buffer; Buffer++) {
|
||||
int64_t OldRes = Result;
|
||||
Result *= 10;
|
||||
Result += *Buffer-'0';
|
||||
inline llvm::ConfigLexerTokens
|
||||
handleContext(const char* tokenText, llvm::ConfigLexerTokens token) {
|
||||
if (ConfigLexerState.in_value) {
|
||||
ConfigLexerState.StringVal = tokenText;
|
||||
return OPTION;
|
||||
}
|
||||
return Result;
|
||||
return token;
|
||||
}
|
||||
|
||||
bool in_value = false;
|
||||
inline llvm::ConfigLexerTokens
|
||||
handleSubstitution(llvm::ConfigLexerTokens token) {
|
||||
if (ConfigLexerState.in_value)
|
||||
return token;
|
||||
YY_FATAL_ERROR("Substitition tokens not allowed in names" );
|
||||
return ERRORTOK;
|
||||
};
|
||||
|
||||
inline llvm::ConfigLexerTokens handleBoolean(llvm::ConfigLexerTokens token) {
|
||||
if (ConfigLexerState.in_value)
|
||||
return token;
|
||||
YY_FATAL_ERROR("Boolean values not allowed in names");
|
||||
return ERRORTOK;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
LANG lang|Lang|LANG
|
||||
PREPROCESSOR preprocessor|PreProcessor|PREPROCESSOR
|
||||
TRANSLATOR translator|Translator|TRANSLATOR
|
||||
OPTIMIZER optimizer|Optimizer|OPTIMIZER
|
||||
ASSEMBLER assembler|Assembler|ASSEMBLER
|
||||
BadSubst \@[^iots][a-zA-Z]\@
|
||||
COMMAND command|Command|COMMAND
|
||||
Comment \#[^\n]*\n
|
||||
NewLine \n
|
||||
Eq \=
|
||||
EscNewLine \\\n
|
||||
GROKS_DASH_O groks_dash_O|Groks_Dash_O|GROKS_DASH_O
|
||||
LANG lang|Lang|LANG
|
||||
LINKER linker|Linker|LINKER
|
||||
NAME name|Name|NAME
|
||||
REQUIRED required|Required|REQUIRED
|
||||
COMMAND command|Command|COMMAND
|
||||
PREPROCESSES preprocesses|PreProcesses|PREPROCESSES
|
||||
GROKS_DASH_O groks_dash_O|Groks_Dash_O|GROKS_DASH_O
|
||||
GROKS_O10N groks_optimization|Groks_Optimization|GROKS_OPTIMIZATION
|
||||
OPTIMIZES optimizes|Optimizes|OPTIMIZES
|
||||
OPT1 opt1|Opt1|OPT1
|
||||
OPT2 opt2|Opt2|OPT2
|
||||
OPT3 opt3|Opt3|OPT3
|
||||
OPT4 opt4|Opt4|OPT4
|
||||
OPT5 opt5|Opt5|OPT5
|
||||
Comment \#[^\n]*
|
||||
NewLine \n
|
||||
White [ \t]*
|
||||
Option [-A-Za-z0-9_:%+/\\|,]*
|
||||
OPTIMIZER optimizer|Optimizer|OPTIMIZER
|
||||
OPTIMIZES optimizes|Optimizes|OPTIMIZES
|
||||
Option [-A-Za-z0-9_:%+/\\|,][-A-Za-z0-9_:%+/\\|,@]*
|
||||
OUTPUT_IS_ASM output_is_asm|Output_Is_Asm|OUTPUT_IS_ASM
|
||||
PREPROCESSES preprocesses|PreProcesses|PREPROCESSES
|
||||
PREPROCESSOR preprocessor|PreProcessor|PREPROCESSOR
|
||||
REQUIRED required|Required|REQUIRED
|
||||
Sep \.
|
||||
Eq \=
|
||||
String \"[^\"]*\"
|
||||
Integer [-+]?[0-9]+
|
||||
TRANSLATES translates|Translates|TRANSLATES
|
||||
TRANSLATOR translator|Translator|TRANSLATOR
|
||||
White [ \t]*
|
||||
|
||||
True true|True|TRUE
|
||||
False false|False|FALSE
|
||||
On on|On|ON
|
||||
@ -94,64 +113,68 @@ No no|No|NO
|
||||
|
||||
%%
|
||||
|
||||
{NewLine} { in_value = false; return EOLTOK; }
|
||||
{Eq} { in_value = true; return EQUALS; }
|
||||
{Comment} { /* Ignore comments */ }
|
||||
{White} { /* Ignore whitespace */ }
|
||||
|
||||
{LANG} { if (in_value) { ConfigLexerData.StringVal = "lang";
|
||||
return OPTION; } else return LANG; }
|
||||
{PREPROCESSOR} { if (in_value) { ConfigLexerData.StringVal = "preprocessor";
|
||||
return OPTION; } else return PREPROCESSOR; }
|
||||
{TRANSLATOR} { if (in_value) { ConfigLexerData.StringVal = "translator";
|
||||
return OPTION; } else return TRANSLATOR; }
|
||||
{OPTIMIZER} { if (in_value) { ConfigLexerData.StringVal = "optimizer";
|
||||
return OPTION; } else return OPTIMIZER; }
|
||||
{ASSEMBLER} { if (in_value) { ConfigLexerData.StringVal = "assembler";
|
||||
return OPTION; } else return ASSEMBLER; }
|
||||
{LINKER} { if (in_value) { ConfigLexerData.StringVal = "linker";
|
||||
return OPTION; } else return LINKER; }
|
||||
{NAME} { if (in_value) { ConfigLexerData.StringVal = "name";
|
||||
return OPTION; } else return NAME; }
|
||||
{REQUIRED} { if (in_value) { ConfigLexerData.StringVal = "required";
|
||||
return OPTION; } else return REQUIRED; }
|
||||
{COMMAND} { if (in_value) { ConfigLexerData.StringVal = "command";
|
||||
return OPTION; } else return COMMAND; }
|
||||
{PREPROCESSES} { if (in_value) { ConfigLexerData.StringVal = "preprocesses";
|
||||
return OPTION; } else return PREPROCESSES; }
|
||||
{GROKS_DASH_O} { if (in_value) { ConfigLexerData.StringVal = "groks_dash_O";
|
||||
return OPTION; } else return GROKS_DASH_O; }
|
||||
{GROKS_O10N} { if (in_value) { ConfigLexerData.StringVal =
|
||||
"groks_optimization"; return OPTION; }
|
||||
else return GROKS_O10N; }
|
||||
{OPTIMIZES} { if (in_value) { ConfigLexerData.StringVal = "optimizes";
|
||||
return OPTION; } else return OPTIMIZES; }
|
||||
{OPT1} { if (in_value) { ConfigLexerData.StringVal = "opt1";
|
||||
return OPTION; } else return OPT1; }
|
||||
{OPT2} { if (in_value) { ConfigLexerData.StringVal = "opt2";
|
||||
return OPTION; } else return OPT2; }
|
||||
{OPT3} { if (in_value) { ConfigLexerData.StringVal = "opt3";
|
||||
return OPTION; } else return OPT3; }
|
||||
{OPT4} { if (in_value) { ConfigLexerData.StringVal = "opt4";
|
||||
return OPTION; } else return OPT4; }
|
||||
{OPT5} { if (in_value) { ConfigLexerData.StringVal = "opt5";
|
||||
return OPTION; } else return OPT5; }
|
||||
@in@ { if (in_value) return IN_SUBST; else return ERRORTOK; }
|
||||
@out@ { if (in_value) return OUT_SUBST; else return ERRORTOK; }
|
||||
{True} { if (in_value) return TRUETOK; else return ERRORTOK; }
|
||||
{On} { if (in_value) return TRUETOK; else return ERRORTOK; }
|
||||
{Yes} { if (in_value) return TRUETOK; else return ERRORTOK; }
|
||||
{False} { if (in_value) return FALSETOK; else return ERRORTOK; }
|
||||
{Off} { if (in_value) return FALSETOK; else return ERRORTOK; }
|
||||
{No} { if (in_value) return FALSETOK; else return ERRORTOK; }
|
||||
{Comment} { /* Ignore comments */
|
||||
ConfigLexerState.in_value = false;
|
||||
ConfigLexerState.lineNum++;
|
||||
return EOLTOK;
|
||||
}
|
||||
|
||||
{Option} { ConfigLexerData.StringVal = yytext; return OPTION; }
|
||||
{Integer} { ConfigLexerData.IntegerVal = IntToVal(yytext); return INTEGER; }
|
||||
{String} { yytext[yyleng-1] = 0; // nuke end quote
|
||||
ConfigLexerData.StringVal = yytext+1; // Nuke start quote
|
||||
{EscNewLine} { ConfigLexerState.lineNum++;
|
||||
/* Don't return EOLTOK! */
|
||||
}
|
||||
|
||||
{NewLine} { ConfigLexerState.in_value = false;
|
||||
ConfigLexerState.lineNum++;
|
||||
return EOLTOK;
|
||||
}
|
||||
|
||||
{Eq} { ConfigLexerState.in_value = true;
|
||||
return EQUALS;
|
||||
}
|
||||
|
||||
{LANG} { return handleContext("lang",LANG); }
|
||||
{PREPROCESSOR} { return handleContext("preprocessor",PREPROCESSOR); }
|
||||
{TRANSLATOR} { return handleContext("translator",TRANSLATOR); }
|
||||
{OPTIMIZER} { return handleContext("optimizer",OPTIMIZER); }
|
||||
{ASSEMBLER} { return handleContext("assembler",ASSEMBLER); }
|
||||
{LINKER} { return handleContext("linker",LINKER); }
|
||||
{NAME} { return handleContext("name",NAME); }
|
||||
{REQUIRED} { return handleContext("required",REQUIRED); }
|
||||
{COMMAND} { return handleContext("command",COMMAND); }
|
||||
{PREPROCESSES} { return handleContext("preprocesses",PREPROCESSES); }
|
||||
{TRANSLATES} { return handleContext("translates",TRANSLATES); }
|
||||
{OPTIMIZES} { return handleContext("optimizes",OPTIMIZES); }
|
||||
{GROKS_DASH_O} { return handleContext("groks_dash_O",GROKS_DASH_O); }
|
||||
{OUTPUT_IS_ASM} { return handleContext("output_ias_asm",OUTPUT_IS_ASM); }
|
||||
{OPT1} { return handleContext("opt1",OPT1); }
|
||||
{OPT2} { return handleContext("opt2",OPT2); }
|
||||
{OPT3} { return handleContext("opt3",OPT3); }
|
||||
{OPT4} { return handleContext("opt4",OPT4); }
|
||||
{OPT5} { return handleContext("opt5",OPT5); }
|
||||
|
||||
@in@ { return handleSubstitution(IN_SUBST); }
|
||||
@out@ { return handleSubstitution(OUT_SUBST); }
|
||||
@time@ { return handleSubstitution(TIME_SUBST); }
|
||||
@stats@ { return handleSubstitution(STATS_SUBST); }
|
||||
@opt@ { return handleSubstitution(OPT_SUBST); }
|
||||
@target@ { return handleSubstitution(TARGET_SUBST); }
|
||||
{BadSubst} { YY_FATAL_ERROR("Invalid substitution token"); }
|
||||
{True} { return handleBoolean(TRUETOK); }
|
||||
{On} { return handleBoolean(TRUETOK); }
|
||||
{Yes} { return handleBoolean(TRUETOK); }
|
||||
{False} { return handleBoolean(FALSETOK); }
|
||||
{Off} { return handleBoolean(FALSETOK); }
|
||||
{No} { return handleBoolean(FALSETOK); }
|
||||
|
||||
{Option} { ConfigLexerState.StringVal = yytext; return OPTION; }
|
||||
{String} { ConfigLexerState.StringVal = yytext+1; // Nuke start quote
|
||||
ConfigLexerState.StringVal.erase(
|
||||
--ConfigLexerState.StringVal.end());
|
||||
return STRING;
|
||||
}
|
||||
{Sep} { if (in_value) { ConfigLexerData.StringVal = yytext;
|
||||
{Sep} { if (ConfigLexerState.in_value) { ConfigLexerState.StringVal = yytext;
|
||||
return OPTION; } }
|
||||
|
||||
|
||||
|
@ -15,21 +15,21 @@
|
||||
#include "ConfigData.h"
|
||||
#include "ConfigLexer.h"
|
||||
#include "CompilerDriver.h"
|
||||
#include "Support/CommandLine.h"
|
||||
#include "Support/StringExtras.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
extern int ::Configlineno;
|
||||
|
||||
namespace llvm {
|
||||
ConfigLexerInfo ConfigLexerData;
|
||||
ConfigLexerInfo ConfigLexerState;
|
||||
InputProvider* ConfigLexerInput = 0;
|
||||
|
||||
InputProvider::~InputProvider() {}
|
||||
void InputProvider::error(const std::string& msg) {
|
||||
std::cerr << name << ":" << Configlineno << ": Error: " << msg << "\n";
|
||||
std::cerr << name << ":" << ConfigLexerState.lineNum << ": Error: " <<
|
||||
msg << "\n";
|
||||
errCount++;
|
||||
}
|
||||
|
||||
@ -65,17 +65,34 @@ namespace {
|
||||
std::ifstream F;
|
||||
};
|
||||
|
||||
cl::opt<bool> DumpTokens("dump-tokens", cl::Optional, cl::Hidden, cl::init(false),
|
||||
cl::desc("Dump lexical tokens (debug use only)."));
|
||||
|
||||
struct Parser
|
||||
{
|
||||
Parser() {
|
||||
token = EOFTOK;
|
||||
provider = 0;
|
||||
confDat = 0;
|
||||
ConfigLexerState.lineNum = 1;
|
||||
ConfigLexerState.in_value = false;
|
||||
ConfigLexerState.StringVal.clear();
|
||||
ConfigLexerState.IntegerVal = 0;
|
||||
};
|
||||
|
||||
ConfigLexerTokens token;
|
||||
InputProvider* provider;
|
||||
CompilerDriver::ConfigData* confDat;
|
||||
CompilerDriver::Action* action;
|
||||
|
||||
int next() { return token = Configlex(); }
|
||||
int next() {
|
||||
token = Configlex();
|
||||
if (DumpTokens)
|
||||
std::cerr << token << "\n";
|
||||
return token;
|
||||
}
|
||||
|
||||
bool next_is_real() {
|
||||
token = Configlex();
|
||||
next();
|
||||
return (token != EOLTOK) && (token != ERRORTOK) && (token != 0);
|
||||
}
|
||||
|
||||
@ -96,7 +113,7 @@ namespace {
|
||||
switch (token ) {
|
||||
case STRING :
|
||||
case OPTION :
|
||||
result += ConfigLexerData.StringVal + " ";
|
||||
result += ConfigLexerState.StringVal + " ";
|
||||
break;
|
||||
default:
|
||||
error("Invalid name");
|
||||
@ -130,15 +147,32 @@ namespace {
|
||||
return result;
|
||||
}
|
||||
|
||||
void parseOptionList(CompilerDriver::StringVector& optList ) {
|
||||
while (next_is_real()) {
|
||||
if (token == STRING || token == OPTION)
|
||||
optList.push_back(ConfigLexerData.StringVal);
|
||||
else {
|
||||
error("Expecting a program option", false);
|
||||
break;
|
||||
}
|
||||
bool parseSubstitution(CompilerDriver::StringVector& optList) {
|
||||
switch (token) {
|
||||
case IN_SUBST: optList.push_back("@in@"); break;
|
||||
case OUT_SUBST: optList.push_back("@out@"); break;
|
||||
case TIME_SUBST: optList.push_back("@time@"); break;
|
||||
case STATS_SUBST: optList.push_back("@stats@"); break;
|
||||
case OPT_SUBST: optList.push_back("@opt@"); break;
|
||||
case TARGET_SUBST: optList.push_back("@target@"); break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void parseOptionList(CompilerDriver::StringVector& optList ) {
|
||||
if (next() == EQUALS) {
|
||||
while (next_is_real()) {
|
||||
if (token == STRING || token == OPTION)
|
||||
optList.push_back(ConfigLexerState.StringVal);
|
||||
else if (!parseSubstitution(optList)) {
|
||||
error("Expecting a program argument or substitution", false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
error("Expecting '='");
|
||||
}
|
||||
|
||||
void parseLang() {
|
||||
@ -174,25 +208,17 @@ namespace {
|
||||
// no value (valid)
|
||||
action.program.clear();
|
||||
action.args.clear();
|
||||
action.inputAt = 0;
|
||||
action.outputAt = 0;
|
||||
} else {
|
||||
if (token == STRING || token == OPTION) {
|
||||
action.program = ConfigLexerData.StringVal;
|
||||
action.program = ConfigLexerState.StringVal;
|
||||
} else {
|
||||
error("Expecting a program name");
|
||||
}
|
||||
while (next_is_real()) {
|
||||
if (token == STRING || token == OPTION) {
|
||||
action.args.push_back(ConfigLexerData.StringVal);
|
||||
} else if (token == IN_SUBST) {
|
||||
action.inputAt = action.args.size();
|
||||
action.args.push_back("@in@");
|
||||
} else if (token == OUT_SUBST) {
|
||||
action.outputAt = action.args.size();
|
||||
action.args.push_back("@out@");
|
||||
} else {
|
||||
error("Expecting a program argument", false);
|
||||
action.args.push_back(ConfigLexerState.StringVal);
|
||||
} else if (!parseSubstitution(action.args)) {
|
||||
error("Expecting a program argument or substitution", false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -246,12 +272,13 @@ namespace {
|
||||
else
|
||||
confDat->Translator.clear(CompilerDriver::GROKS_DASH_O_FLAG);
|
||||
break;
|
||||
case GROKS_O10N:
|
||||
case OUTPUT_IS_ASM:
|
||||
if (parseBoolean())
|
||||
confDat->Translator.set(CompilerDriver::GROKS_O10N_FLAG);
|
||||
confDat->Translator.set(CompilerDriver::OUTPUT_IS_ASM_FLAG);
|
||||
else
|
||||
confDat->Translator.clear(CompilerDriver::GROKS_O10N_FLAG);
|
||||
confDat->Translator.clear(CompilerDriver::OUTPUT_IS_ASM_FLAG);
|
||||
break;
|
||||
|
||||
default:
|
||||
error("Expecting 'command', 'required', 'preprocesses', "
|
||||
"'groks_dash_O' or 'optimizes'");
|
||||
@ -264,17 +291,29 @@ namespace {
|
||||
case COMMAND:
|
||||
parseCommand(confDat->Optimizer);
|
||||
break;
|
||||
case PREPROCESSES:
|
||||
if (parseBoolean())
|
||||
confDat->Optimizer.set(CompilerDriver::PREPROCESSES_FLAG);
|
||||
else
|
||||
confDat->Optimizer.clear(CompilerDriver::PREPROCESSES_FLAG);
|
||||
break;
|
||||
case TRANSLATES:
|
||||
if (parseBoolean())
|
||||
confDat->Optimizer.set(CompilerDriver::TRANSLATES_FLAG);
|
||||
else
|
||||
confDat->Optimizer.clear(CompilerDriver::TRANSLATES_FLAG);
|
||||
break;
|
||||
case GROKS_DASH_O:
|
||||
if (parseBoolean())
|
||||
confDat->Optimizer.set(CompilerDriver::GROKS_DASH_O_FLAG);
|
||||
else
|
||||
confDat->Optimizer.clear(CompilerDriver::GROKS_DASH_O_FLAG);
|
||||
break;
|
||||
case GROKS_O10N:
|
||||
case OUTPUT_IS_ASM:
|
||||
if (parseBoolean())
|
||||
confDat->Optimizer.set(CompilerDriver::GROKS_O10N_FLAG);
|
||||
confDat->Translator.set(CompilerDriver::OUTPUT_IS_ASM_FLAG);
|
||||
else
|
||||
confDat->Optimizer.clear(CompilerDriver::GROKS_O10N_FLAG);
|
||||
confDat->Translator.clear(CompilerDriver::OUTPUT_IS_ASM_FLAG);
|
||||
break;
|
||||
default:
|
||||
error("Expecting 'command' or 'groks_dash_O'");
|
||||
@ -304,12 +343,6 @@ namespace {
|
||||
else
|
||||
confDat->Linker.clear(CompilerDriver::GROKS_DASH_O_FLAG);
|
||||
break;
|
||||
case GROKS_O10N:
|
||||
if (parseBoolean())
|
||||
confDat->Linker.set(CompilerDriver::GROKS_O10N_FLAG);
|
||||
else
|
||||
confDat->Linker.clear(CompilerDriver::GROKS_O10N_FLAG);
|
||||
break;
|
||||
default:
|
||||
error("Expecting 'command'");
|
||||
break;
|
||||
@ -349,7 +382,6 @@ namespace {
|
||||
p.token = EOFTOK;
|
||||
p.provider = &provider;
|
||||
p.confDat = &confDat;
|
||||
p.action = 0;
|
||||
p.parseFile();
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,6 @@
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../..
|
||||
TOOLNAME = llvmc
|
||||
USEDLIBS = asmparser bcreader bcwriter vmcore support.a system.a
|
||||
USEDLIBS = support.a
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
@ -4,7 +4,6 @@
|
||||
preprocessor.required=false
|
||||
translator.command=llvm-as @in@ -o @out@
|
||||
translator.groks_dash_O=no
|
||||
translator.groks_optimization=no
|
||||
translator.optimizes=no
|
||||
translator.preprocesses=true
|
||||
translator.required=TRUE
|
||||
|
@ -26,7 +26,7 @@ namespace {
|
||||
//===------------------------------------------------------------------------===
|
||||
//=== PHASE OPTIONS
|
||||
//===------------------------------------------------------------------------===
|
||||
static cl::opt<CompilerDriver::Phases> FinalPhase(
|
||||
cl::opt<CompilerDriver::Phases> FinalPhase(
|
||||
cl::desc("Choose final phase of compilation:"),
|
||||
cl::init(CompilerDriver::LINKING),
|
||||
cl::values(
|
||||
@ -45,7 +45,7 @@ static cl::opt<CompilerDriver::Phases> FinalPhase(
|
||||
//===------------------------------------------------------------------------===
|
||||
//=== OPTIMIZATION OPTIONS
|
||||
//===------------------------------------------------------------------------===
|
||||
static cl::opt<CompilerDriver::OptimizationLevels> OptLevel(
|
||||
cl::opt<CompilerDriver::OptimizationLevels> OptLevel(
|
||||
cl::desc("Choose level of optimization to apply:"),
|
||||
cl::init(CompilerDriver::OPT_FAST_COMPILE),
|
||||
cl::values(
|
||||
@ -69,23 +69,23 @@ static cl::opt<CompilerDriver::OptimizationLevels> OptLevel(
|
||||
//=== TOOL OPTIONS
|
||||
//===------------------------------------------------------------------------===
|
||||
|
||||
static cl::list<std::string> PreprocessorToolOpts("Tpre", cl::ZeroOrMore,
|
||||
cl::list<std::string> PreprocessorToolOpts("Tpre", cl::ZeroOrMore,
|
||||
cl::desc("Pass specific options to the pre-processor"),
|
||||
cl::value_desc("option"));
|
||||
|
||||
static cl::list<std::string> TranslatorToolOpts("Ttrn", cl::ZeroOrMore,
|
||||
cl::list<std::string> TranslatorToolOpts("Ttrn", cl::ZeroOrMore,
|
||||
cl::desc("Pass specific options to the assembler"),
|
||||
cl::value_desc("option"));
|
||||
|
||||
static cl::list<std::string> AssemblerToolOpts("Tasm", cl::ZeroOrMore,
|
||||
cl::list<std::string> AssemblerToolOpts("Tasm", cl::ZeroOrMore,
|
||||
cl::desc("Pass specific options to the assembler"),
|
||||
cl::value_desc("option"));
|
||||
|
||||
static cl::list<std::string> OptimizerToolOpts("Topt", cl::ZeroOrMore,
|
||||
cl::list<std::string> OptimizerToolOpts("Topt", cl::ZeroOrMore,
|
||||
cl::desc("Pass specific options to the optimizer"),
|
||||
cl::value_desc("option"));
|
||||
|
||||
static cl::list<std::string> LinkerToolOpts("Tlnk", cl::ZeroOrMore,
|
||||
cl::list<std::string> LinkerToolOpts("Tlnk", cl::ZeroOrMore,
|
||||
cl::desc("Pass specific options to the linker"),
|
||||
cl::value_desc("option"));
|
||||
|
||||
@ -93,10 +93,10 @@ static cl::list<std::string> LinkerToolOpts("Tlnk", cl::ZeroOrMore,
|
||||
//=== INPUT OPTIONS
|
||||
//===------------------------------------------------------------------------===
|
||||
|
||||
static cl::list<std::string> LibPaths("L", cl::Prefix,
|
||||
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::list<std::string> Libraries("l", cl::Prefix,
|
||||
cl::desc("Specify libraries to link to"), cl::value_desc("library prefix"));
|
||||
|
||||
|
||||
@ -104,40 +104,46 @@ static cl::list<std::string> Libraries("l", cl::Prefix,
|
||||
//=== OUTPUT OPTIONS
|
||||
//===------------------------------------------------------------------------===
|
||||
|
||||
static cl::opt<std::string> OutputFilename("o",
|
||||
cl::opt<std::string> OutputFilename("o",
|
||||
cl::desc("Override output filename"), cl::value_desc("filename"));
|
||||
|
||||
static cl::opt<std::string> OutputMachine("m", cl::Prefix,
|
||||
cl::opt<std::string> OutputMachine("m", cl::Prefix,
|
||||
cl::desc("Specify a target machine"), cl::value_desc("machine"));
|
||||
|
||||
static cl::opt<bool> Native("native", cl::init(false),
|
||||
cl::opt<bool> Native("native", cl::init(false),
|
||||
cl::desc("Generative native object and executables instead of bytecode"));
|
||||
|
||||
//===------------------------------------------------------------------------===
|
||||
//=== INFORMATION OPTIONS
|
||||
//===------------------------------------------------------------------------===
|
||||
|
||||
static cl::opt<bool> DryRun("dry-run", cl::Optional, cl::init(false),
|
||||
cl::opt<bool> DryRun("dry-run", cl::Optional, cl::init(false),
|
||||
cl::desc("Do everything but perform the compilation actions"));
|
||||
|
||||
static cl::alias DryRunAlias("y", cl::Optional,
|
||||
cl::alias DryRunAlias("y", cl::Optional,
|
||||
cl::desc("Alias for -dry-run"), cl::aliasopt(DryRun));
|
||||
|
||||
static cl::opt<bool> Verbose("verbose", cl::Optional, cl::init(false),
|
||||
cl::opt<bool> Verbose("verbose", cl::Optional, cl::init(false),
|
||||
cl::desc("Print out each action taken"));
|
||||
|
||||
static cl::alias VerboseAlias("v", cl::Optional,
|
||||
cl::alias VerboseAlias("v", cl::Optional,
|
||||
cl::desc("Alias for -verbose"), cl::aliasopt(Verbose));
|
||||
|
||||
static cl::opt<bool> Debug("debug", cl::Optional, cl::init(false),
|
||||
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::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),
|
||||
cl::opt<bool> TimeActions("time-actions", cl::Optional, cl::init(false),
|
||||
cl::desc("Print execution time for each action taken"));
|
||||
|
||||
cl::opt<bool> TimePasses("time-passes", cl::Optional, cl::init(false),
|
||||
cl::desc("Print execution time for each optimization pass"));
|
||||
|
||||
cl::opt<bool> ShowStats("stats", cl::Optional, cl::init(false),
|
||||
cl::desc("Print statistics accumulated during optimization"));
|
||||
|
||||
//===------------------------------------------------------------------------===
|
||||
//=== ADVANCED OPTIONS
|
||||
//===------------------------------------------------------------------------===
|
||||
@ -152,6 +158,9 @@ static cl::opt<bool> EmitRawCode("emit-raw-code", cl::Hidden, cl::Optional,
|
||||
static cl::opt<bool> PipeCommands("pipe", cl::Optional,
|
||||
cl::desc("Invoke sub-commands by linking input/output with pipes"));
|
||||
|
||||
static cl::opt<bool> KeepTemporaries("keep-temps", cl::Optional,
|
||||
cl::desc("Don't delete the temporary files created during compilation"));
|
||||
|
||||
//===------------------------------------------------------------------------===
|
||||
//=== POSITIONAL OPTIONS
|
||||
//===------------------------------------------------------------------------===
|
||||
@ -192,86 +201,97 @@ const std::string GetFileType(const std::string& fname, unsigned pos ) {
|
||||
|
||||
/// @brief The main program for llvmc
|
||||
int main(int argc, char **argv) {
|
||||
// Make sure we print stack trace if we get bad signals
|
||||
PrintStackTraceOnErrorSignal();
|
||||
try {
|
||||
// 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"
|
||||
);
|
||||
// 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"
|
||||
);
|
||||
|
||||
// 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";
|
||||
if (PipeCommands)
|
||||
std::cerr << argv[0] << ": Not implemented yet: -pipe";
|
||||
// Deal with unimplemented options.
|
||||
if (PipeCommands)
|
||||
std::cerr << argv[0] << ": Not implemented yet: -pipe";
|
||||
|
||||
// Default the output file, only if we're going to try to link
|
||||
if (OutputFilename.empty() && OptLevel == CompilerDriver::LINKING)
|
||||
OutputFilename = "a.out";
|
||||
// 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;
|
||||
Provider.setConfigDir(ConfigDir);
|
||||
// Construct the ConfigDataProvider object
|
||||
LLVMC_ConfigDataProvider Provider;
|
||||
Provider.setConfigDir(ConfigDir);
|
||||
|
||||
// Construct the CompilerDriver object
|
||||
CompilerDriver CD(Provider);
|
||||
// Construct the CompilerDriver object
|
||||
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);
|
||||
CD.setLibraryPaths(LibPaths);
|
||||
CD.setPreprocessorOptions(PreprocessorToolOpts);
|
||||
CD.setTranslatorOptions(TranslatorToolOpts);
|
||||
CD.setOptimizerOptions(OptimizerToolOpts);
|
||||
CD.setAssemblerOptions(AssemblerToolOpts);
|
||||
CD.setLinkerOptions(LinkerToolOpts);
|
||||
// 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);
|
||||
CD.setTimeActions(TimeActions);
|
||||
CD.setTimePasses(TimePasses);
|
||||
CD.setShowStats(ShowStats);
|
||||
CD.setKeepTemporaries(KeepTemporaries);
|
||||
CD.setLibraryPaths(LibPaths);
|
||||
if (!PreprocessorToolOpts.empty())
|
||||
CD.setPhaseArgs(CompilerDriver::PREPROCESSING, PreprocessorToolOpts);
|
||||
if (!TranslatorToolOpts.empty())
|
||||
CD.setPhaseArgs(CompilerDriver::TRANSLATION, TranslatorToolOpts);
|
||||
if (!OptimizerToolOpts.empty())
|
||||
CD.setPhaseArgs(CompilerDriver::OPTIMIZATION, OptimizerToolOpts);
|
||||
if (!AssemblerToolOpts.empty())
|
||||
CD.setPhaseArgs(CompilerDriver::ASSEMBLY,AssemblerToolOpts);
|
||||
if (!LinkerToolOpts.empty())
|
||||
CD.setPhaseArgs(CompilerDriver::LINKING, LinkerToolOpts);
|
||||
|
||||
// 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;
|
||||
// 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;
|
||||
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
|
||||
}
|
||||
else if ( libPos != 0 && (filePos == 0 || libPos < filePos) ) {
|
||||
// Add a library
|
||||
InpList.push_back( std::make_pair(*libIt++,""));
|
||||
|
||||
// Tell the driver to do its thing
|
||||
int result = CD.execute(InpList,OutputFilename);
|
||||
if (result != 0) {
|
||||
std::cerr << argv[0] << ": Error executing actions. Terminated.\n";
|
||||
return result;
|
||||
}
|
||||
else
|
||||
break; // we're done with the list
|
||||
}
|
||||
|
||||
// Tell the driver to do its thing
|
||||
int result = CD.execute(InpList,OutputFilename);
|
||||
if (result != 0) {
|
||||
std::cerr << argv[0] << ": Error executing actions. Terminated.\n";
|
||||
return result;
|
||||
// All is good, return success
|
||||
return 0;
|
||||
} catch (std::string& msg) {
|
||||
std::cerr << msg << "\n";
|
||||
} catch (...) {
|
||||
std::cerr << "Unexpected unknown exception occurred.\n";
|
||||
}
|
||||
|
||||
// All is good, return success
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,22 +1,72 @@
|
||||
# Stacker CompilerDriver Configuration File
|
||||
# Stacker Configuration File For llvmc
|
||||
|
||||
##########################################################
|
||||
# Language definitions
|
||||
##########################################################
|
||||
lang.name=Stacker
|
||||
lang.opt1=-simplifycfg -instcombine -mem2reg
|
||||
lang.opt2=-simplifycfg -instcombine -mem2reg -scalarrepl -sccp
|
||||
lang.opt3=-simplifycfg -instcombine -mem2reg -scalarrepl -sccp \
|
||||
-branch-combine -adce -globaldce -inline -licm -pre
|
||||
lang.opt4=-simplifycfg -instcombine -mem2reg -scalarrepl -sccp \
|
||||
-ipconstprop -branch-combine -adce -globaldce -inline -licm -pre
|
||||
lang.opt5=-simplifycfg -instcombine -mem2reg -scalarrepl -sccp \
|
||||
-ipconstprop -branch-combine -adce -globaldce -inline -licm -pre \
|
||||
-block-placement
|
||||
|
||||
##########################################################
|
||||
# Pre-processor definitions
|
||||
##########################################################
|
||||
|
||||
# Stacker doesn't have a preprocessor but the following
|
||||
# allows the -E option to be supported
|
||||
preprocessor.command=cp @in@ @out@
|
||||
preprocessor.required=False
|
||||
preprocessor.required=false
|
||||
|
||||
##########################################################
|
||||
# Translator definitions
|
||||
translator.command=stkrc -S 2048 @in@ -o @out@
|
||||
translator.preprocesses=false
|
||||
translator.optimizes=TRUE
|
||||
translator.groks_dash_O=No
|
||||
translator.required=no
|
||||
##########################################################
|
||||
|
||||
# To compile stacker source, we just run the stacker
|
||||
# compiler with a default stack size of 2048 entries.
|
||||
translator.command=stkrc -s 2048 @in@ -o @out@ @time@ @stats@
|
||||
|
||||
# stkrc doesn't preprocess but we set this to true so
|
||||
# that we don't run the cp command by default.
|
||||
translator.preprocesses=true
|
||||
|
||||
# The translator is required to run.
|
||||
translator.required=true
|
||||
|
||||
# stkrc doesn't do any optimization, it just translates
|
||||
translator.optimizes=no
|
||||
|
||||
# stkrc doesn't handle the -On options
|
||||
translator.groks_dash_O=no
|
||||
|
||||
##########################################################
|
||||
# Optimizer definitions
|
||||
optimizer.command=opt @in@ -o @out@
|
||||
##########################################################
|
||||
|
||||
# For optimization, we use the LLVM "opt" program
|
||||
optimizer.command=opt @in@ -o @out@ @opt@ @time@ @stats@
|
||||
|
||||
# opt doesn't (yet) grok -On
|
||||
optimizer.groks_dash_O=no
|
||||
|
||||
# opt doesn't translate
|
||||
optimizer.translates = no
|
||||
|
||||
# opt doesn't preprocess
|
||||
optimizer.preprocesses=no
|
||||
|
||||
##########################################################
|
||||
# Assembler definitions
|
||||
assembler.command=llc @in@ -o @out@
|
||||
##########################################################
|
||||
assembler.command=llc @in@ -o @out@ @target@ "-regalloc=linearscan" \
|
||||
@time@ @stats@
|
||||
|
||||
##########################################################
|
||||
# Linker definitions
|
||||
linker.command=llvm-link @in@ -o @out@
|
||||
##########################################################
|
||||
linker.command=gccld @in@ -o @out@ -lstkr_runtime
|
||||
|
Loading…
Reference in New Issue
Block a user