summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/llvmc/CompilerDriver.cpp48
-rw-r--r--tools/llvmc/CompilerDriver.h6
-rw-r--r--tools/llvmc/ConfigData.cpp601
-rw-r--r--tools/llvmc/ConfigData.h3
-rw-r--r--tools/llvmc/ConfigLexer.h77
-rw-r--r--tools/llvmc/ConfigLexer.l135
-rw-r--r--tools/llvmc/Configuration.cpp601
-rw-r--r--tools/llvmc/Configuration.h3
-rw-r--r--tools/llvmc/llvmc.cpp1
9 files changed, 752 insertions, 723 deletions
diff --git a/tools/llvmc/CompilerDriver.cpp b/tools/llvmc/CompilerDriver.cpp
index f1d3e58bad..ff63b2100e 100644
--- a/tools/llvmc/CompilerDriver.cpp
+++ b/tools/llvmc/CompilerDriver.cpp
@@ -29,8 +29,38 @@ namespace {
if ( dotpos = std::string::npos ) return "";
return fullName.substr(dotpos+1);
}
+
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()) {
+ std::cerr << " " + *I;
+ ++I;
+ }
+ std::cerr << "\n";
+ }
+
+ void DumpConfigData(CompilerDriver::ConfigData* cd, const std::string& type ){
+ std::cerr << "Configuration Data For '" << cd->langName << "' (" << type
+ << ")\n";
+ std::cerr << "translator.preprocesses=" << cd->TranslatorPreprocesses
+ << "\n";
+ std::cerr << "translator.groks_dash_O=" << cd->TranslatorGroksDashO << "\n";
+ std::cerr << "translator.optimizes=" << cd->TranslatorOptimizes << "\n";
+ std::cerr << "preprocessor.needed=" << cd->PreprocessorNeeded << "\n";
+ std::cerr << "PreProcessor: ";
+ WriteAction(&cd->PreProcessor);
+ std::cerr << "Translator: ";
+ WriteAction(&cd->Translator);
+ std::cerr << "Optimizer: ";
+ WriteAction(&cd->Optimizer);
+ std::cerr << "Assembler: ";
+ WriteAction(&cd->Assembler);
+ std::cerr << "Linker: ";
+ WriteAction(&cd->Linker);
+ }
}
@@ -80,21 +110,13 @@ CompilerDriver::Action* CompilerDriver::GetAction(ConfigData* cd,
}
assert(pat != 0 && "Invalid command pattern");
Action* a = new Action(*pat);
- a->args[pat->inputAt] = input;
- a->args[pat->outputAt] = output;
+ if (pat->inputAt < a->args.size())
+ a->args[pat->inputAt] = input;
+ if (pat->outputAt < a->args.size())
+ 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)
@@ -170,6 +192,8 @@ int CompilerDriver::execute(const InputList& InpList,
if (cd == 0)
error(std::string("Files of type '") + I->second +
"' are not recognized." );
+ if (isDebug)
+ DumpConfigData(cd,I->second);
// We have valid configuration data, now figure out where the output
// of compilation should end up.
diff --git a/tools/llvmc/CompilerDriver.h b/tools/llvmc/CompilerDriver.h
index d6587b0aa9..f49a780ba5 100644
--- a/tools/llvmc/CompilerDriver.h
+++ b/tools/llvmc/CompilerDriver.h
@@ -58,6 +58,7 @@ namespace llvm {
/// @brief A structure to hold the action data for a given source
/// language.
struct Action {
+ Action() : inputAt(0) , outputAt(0) {}
std::string program; ///< The program to execve
std::vector<std::string> args; ///< Arguments to the program
size_t inputAt; ///< Argument index to insert input file
@@ -65,6 +66,10 @@ namespace llvm {
};
struct ConfigData {
+ ConfigData() : TranslatorPreprocesses(false),
+ TranslatorOptimizes(false),
+ TranslatorGroksDashO(false),
+ PreprocessorNeeded(false) {}
std::string langName; ///< The name of the source language
bool TranslatorPreprocesses;///< Translator program will pre-process
bool TranslatorOptimizes; ///< Translator program will optimize too
@@ -155,7 +160,6 @@ namespace llvm {
private:
Action* GetAction(ConfigData* cd, const std::string& input,
const std::string& output, Phases phase );
- void WriteAction(Action* a);
void DoAction(Action* a);
/// @}
diff --git a/tools/llvmc/ConfigData.cpp b/tools/llvmc/ConfigData.cpp
index 94949c405d..d2e788bf12 100644
--- a/tools/llvmc/ConfigData.cpp
+++ b/tools/llvmc/ConfigData.cpp
@@ -13,391 +13,282 @@
//===------------------------------------------------------------------------===
#include "ConfigData.h"
+#include "ConfigLexer.h"
#include "CompilerDriver.h"
#include "Support/StringExtras.h"
#include <iostream>
+#include <fstream>
using namespace llvm;
-namespace {
+extern int ::Configlex();
-// This array of strings provides the input for ".ll" files (LLVM Assembly)
-// to the configuration file parser. This data is just "built-in" to
-// llvmc so it doesn't have to be read from a configuration file.
-static const char* LL_Data[] = {
- "lang.name=LLVM Assembly",
- "lang.translator.preprocesses=false",
- "lang.translator.optimizes=No",
- "lang.translator.groks_dash_O=No",
- "lang.preprocessor.needed=0",
- "preprocessor.prog=",
- "preprocessor.args=",
- "translator.prog=llvm-as",
- "translator.args=@in@ -o @out@",
- "optimizer.prog=opt",
- "optimizer.args=@in@ -o @out@",
- "assembler.prog=llc",
- "assembler.args=@in@ -o @out@",
- "linker.prog=llvm-link",
- "linker.args=@in@ -o @out@"
-};
-
-// This array of strings provides the input for ".st" files (Stacker).
-static const char* ST_Data[] = {
- "lang.name=Stacker",
- "lang.translator.preprocesses=false",
- "lang.translator.optimizes=true",
- "lang.translator.groks_dash_O=0",
- "lang.preprocessor.needed=0",
- "preprocessor.prog=cp",
- "preprocessor.args=@in@ @out@",
- "translator.prog=stkrc",
- "translator.args=@in@ -o @out@ -S 2048",
- "optimizer.prog=opt",
- "optimizer.args=@in@ -o @out@",
- "assembler.prog=llc",
- "assembler.args=@in@ -o @out@",
- "linker.prog=llvm-link",
- "linker.args=@in@ -o @out@"
-};
-
-class InputProvider {
- public:
- virtual bool getLine(std::string& line) = 0;
- virtual void error(const std::string& msg) = 0;
- virtual bool errorOccurred() = 0;
-};
-
-class StaticInputProvider : public InputProvider {
- public:
- StaticInputProvider(const char *data[], size_t count,
- const std::string& nam) {
- TheData = data;
- limit = count;
- where = 0;
- name = nam;
- errCount = 0;
- }
- virtual ~StaticInputProvider() {}
- virtual bool getLine(std::string& line) {
- if ( where >= limit ) return false;
- line = TheData[where++];
- return true;
- }
+namespace llvm {
+ ConfigLexerInfo ConfigLexerData;
+ InputProvider* ConfigLexerInput = 0;
+ unsigned ConfigLexerLine = 1;
- virtual void error(const std::string& msg) {
- std::cerr << name << ":" << where << ": Error: " << msg << "\n";
- errCount++;
+ InputProvider::~InputProvider() {}
+ void InputProvider::error(const std::string& msg) {
+ std::cerr << name << ":" << ConfigLexerLine << ": Error: " << msg << "\n";
+ errCount++;
+ }
+
+ void InputProvider::checkErrors() {
+ if (errCount > 0) {
+ std::cerr << name << " had " << errCount << " errors. Terminating.\n";
+ exit(errCount);
}
+ }
- virtual bool errorOccurred() { return errCount > 0; };
+}
- private:
- const char**TheData;
- size_t limit;
- size_t where;
- std::string name;
- size_t errCount;
-};
+namespace {
-inline bool recognize(const char*& p, const char*token) {
- while (*p == *token && *token != '\0')
- ++token, p++;
- return *token == '\0' && ((*p == '\0') || ( *p == '.' ) || (*p == '='));
-}
+ class FileInputProvider : public InputProvider {
+ public:
+ FileInputProvider(const std::string & fname)
+ : InputProvider(fname)
+ , F(fname.c_str()) {
+ ConfigLexerInput = this;
+ }
+ virtual ~FileInputProvider() { F.close(); ConfigLexerInput = 0; }
+ virtual unsigned read(char *buffer, unsigned max_size) {
+ if (F.good()) {
+ F.read(buffer,max_size);
+ if ( F.gcount() ) return F.gcount() - 1;
+ }
+ return 0;
+ }
+
+ bool okay() { return F.good(); }
+ private:
+ std::ifstream F;
+ };
+
+ struct ParseContext
+ {
+ int token;
+ InputProvider* provider;
+ CompilerDriver::ConfigData* confDat;
+ CompilerDriver::Action* action;
+
+ int next() { return token = Configlex(); }
+
+ bool next_is_real() {
+ token = Configlex();
+ return (token != EOLTOK) && (token != ERRORTOK) && (token != 0);
+ }
-inline bool getBoolean(const std::string& value) {
- switch (value[0]) {
- case 't':
- case 'T':
- case '1':
- case 'y':
- case 'Y':
- return true;
- default :
- return false;
- }
- return false;
-}
+ void eatLineRemnant() {
+ while (next_is_real()) ;
+ }
-inline void skipWhitespace( size_t& pos, const std::string& line ) {
- while (pos < line.size() && (
- line[pos] == ' ' || // Space
- line[pos] == '\t' || // Horizontal Tab
- line[pos] == '\n' || // New Line
- line[pos] == '\v' || // Vertical Tab
- line[pos] == '\f' || // Form Feed
- line[pos] == '\r') // Carriate Return
- )
- pos++;
-}
+ void error(const std::string& msg, bool skip = true) {
+ provider->error(msg);
+ if (skip)
+ eatLineRemnant();
+ }
-inline void parseArgs(CompilerDriver::Action& pat,
- const std::string& value,
- InputProvider& provider )
-{
- const char* p = value.c_str();
- const char* argStart = p;
- while (*p != '\0') {
- switch (*p) {
- case ' ':
- if (argStart != p)
- pat.args.push_back(std::string(argStart, p-argStart));
- argStart = ++p;
- break;
- case '@' :
- {
- if (argStart != p)
- pat.args.push_back(std::string(argStart,p-argStart));
- const char* token = ++p;
- while (*p != '@' && *p != 0)
- p++;
- if ( *p != '@' ) {
- provider.error("Unterminated substitution token");
- return;
- } else {
- p++;
- bool legal = false;
- switch (token[0]) {
- case 'i':
- if (token[1] == 'n' && token[2] == '@' ) {
- pat.inputAt = pat.args.size();
- pat.args.push_back("in");
- legal = true;
- argStart = p;
- }
- break;
- case 'o':
- if (token[1] == 'u' && token[2] == 't' && token[3] == '@') {
- pat.outputAt = pat.args.size();
- pat.args.push_back("out");
- legal = true;
- argStart = p;
- }
- break;
- default:
- break;
- }
- if (!legal) {
- provider.error("Invalid substitution token");
- return;
- }
+ std::string parseName() {
+ std::string result;
+ if (next() == EQUALS) {
+ while (next_is_real()) {
+ switch (token ) {
+ case STRING :
+ case OPTION :
+ result += ConfigLexerData.StringVal + " ";
+ break;
+ default:
+ error("Invalid name");
+ break;
}
}
- break;
- default :
- p++;
- break;
+ if (result.empty())
+ error("Name exepected");
+ else
+ result.erase(result.size()-1,1);
+ } else
+ error("= expected");
+ return result;
}
- }
-}
-CompilerDriver::ConfigData*
-ParseConfigData(InputProvider& provider) {
- std::string line;
- CompilerDriver::ConfigData data;
- while ( provider.getLine(line) ) {
- // Check line length first
- size_t lineLen = line.size();
- if (lineLen > 4096)
- provider.error("length of input line (" + utostr(lineLen) +
- ") is too long");
-
- // First, skip whitespace
- size_t stPos = 0;
- skipWhitespace(stPos, line);
-
- // See if there's a hash mark. It and everything after it is
- // ignored so lets delete that now.
- size_t hashPos = line.find('#');
- if (hashPos != std::string::npos)
- line.erase(hashPos);
-
- // Make sure we have something left to parse
- if (line.size() == 0)
- continue; // ignore full-line comment or whitespace line
-
- // Find the equals sign
- size_t eqPos = line.find('=');
- if (eqPos == std::string::npos)
- provider.error("Configuration directive is missing an =");
-
- // extract the item name
- std::string name(line, stPos, eqPos-stPos);
-
- // directives without names are illegal
- if (name.empty())
- provider.error("Configuration directive name is empty");
-
- // Skip whitespace in the value
- size_t valPos = eqPos + 1;
- skipWhitespace(valPos, line);
-
- // Skip white space at end of value
- size_t endPos = line.length() - 1;
- while (line[endPos] == ' ')
- endPos--;
-
- // extract the item value
- std::string value(line, valPos, endPos-valPos+1);
-
- // Get the configuration item as a char pointer
- const char*p = name.c_str();
-
- // Indicate we haven't found an invalid item yet.
- bool invalidItem = false;
-
- // Parse the contents by examining first character and
- // using the recognize function strategically
- switch (*p++) {
- case 'l' :
- // could it be "lang."
- if (*p == 'a') { // "lang." ?
- if (recognize(p,"ang")) {
- p++;
- switch (*p++) {
- case 'n':
- if (recognize(p,"ame"))
- data.langName = value;
- else
- invalidItem = true;
- break;
- case 't':
- if (recognize(p,"ranslator")) {
- p++;
- if (recognize(p,"preprocesses"))
- data.TranslatorPreprocesses = getBoolean(value);
- else if (recognize(p, "optimizes"))
- data.TranslatorOptimizes = getBoolean(value);
- else if (recognize(p, "groks_dash_O"))
- data.TranslatorGroksDashO = getBoolean(value);
- else
- invalidItem = true;
- }
- else
- invalidItem = true;
- break;
- case 'p':
- if (recognize(p,"reprocessor")) {
- p++;
- if (recognize(p,"needed")) {
- data.PreprocessorNeeded = getBoolean(value);
- } else
- invalidItem = true;
- }
- else
- invalidItem = true;
- break;
-
- default:
- invalidItem = true;
- break;
- }
- }
- } else if (*p == 'i') { // "linker." ?
- if (recognize(p,"inker")) {
- p++;
- if (recognize(p,"prog"))
- data.Linker.program = value;
- else if (recognize(p,"args"))
- parseArgs(data.Linker,value,provider);
- else
- invalidItem = true;
- }
- else
- invalidItem = true;
- } else {
- invalidItem = true;
+ bool parseBoolean() {
+ bool result = true;
+ if (next() == EQUALS) {
+ if (next() == FALSETOK) {
+ result = false;
+ } else if (token != TRUETOK) {
+ error("Expecting boolean value");
+ return false;
}
- break;
-
- case 'p' :
- if (*p == 'r') { // "preprocessor." ?
- if (recognize(p, "reprocessor")) {
- p++;
- if (recognize(p,"prog"))
- data.PreProcessor.program = value;
- else if (recognize(p,"args"))
- parseArgs(data.PreProcessor,value,provider);
- else
- invalidItem = true;
- } else
- invalidItem = true;
- } else {
- invalidItem = true;
+ if (next() != EOLTOK && token != 0) {
+ error("Extraneous tokens after boolean");
}
- break;
-
- case 't' :
- if (*p == 'r') { // "translator." ?
- if (recognize(p, "ranslator")) {
- p++;
- if (recognize(p,"prog"))
- data.Translator.program = value;
- else if (recognize(p,"args"))
- parseArgs(data.Translator,value,provider);
- else
- invalidItem = true;
- } else
- invalidItem = true;
- } else {
- invalidItem = true;
- }
- break;
-
- case 'o' :
- if (*p == 'p') { // "optimizer." ?
- if (recognize(p, "ptimizer")) {
- p++;
- if (recognize(p,"prog"))
- data.Optimizer.program = value;
- else if (recognize(p,"args"))
- parseArgs(data.Optimizer,value,provider);
- else
- invalidItem = true;
- } else
- invalidItem = true;
- } else {
- invalidItem = true;
+ }
+ else
+ error("Expecting '='");
+ return result;
+ }
+
+ void parseLang() {
+ if ( next() == NAME ) {
+ confDat->langName = parseName();
+ } else if (token == TRANSLATOR) {
+ switch (next()) {
+ case PREPROCESSES:
+ confDat->TranslatorPreprocesses = parseBoolean();
+ break;
+ case OPTIMIZES:
+ confDat->TranslatorOptimizes = parseBoolean();
+ break;
+ case GROKS_DASH_O:
+ confDat->TranslatorGroksDashO = parseBoolean();
+ break;
+ default:
+ error("Invalid lang.translator identifier");
+ break;
}
- break;
- case 'a' :
- if (*p == 's') { // "assembler." ?
- if (recognize(p, "ssembler")) {
- p++;
- if (recognize(p,"prog"))
- data.Assembler.program = value;
- else if (recognize(p,"args"))
- parseArgs(data.Assembler,value,provider);
- else
- invalidItem = true;
- } else
- invalidItem = true;
+ }
+ else if (token == PREPROCESSOR) {
+ if (next() == NEEDED)
+ confDat->PreprocessorNeeded = parseBoolean();
+ }
+ else {
+ error("Expecting valid identifier after 'lang.'");
+ }
+ }
+
+ void parseCommand(CompilerDriver::Action& action) {
+ if (next() == EQUALS) {
+ next();
+ if (token == EOLTOK) {
+ // no value (valid)
+ action.program.clear();
+ action.args.clear();
+ action.inputAt = 0;
+ action.outputAt = 0;
} else {
- invalidItem = true;
+ if (token == STRING || token == OPTION) {
+ action.program = ConfigLexerData.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);
+ }
}
- break;
+ }
+ }
+
+ void parsePreProcessor() {
+ if (next() != COMMAND) {
+ error("Expecting 'command'");
+ return;
+ }
+ parseCommand(confDat->PreProcessor);
+ }
+
+ void parseTranslator() {
+ if (next() != COMMAND) {
+ error("Expecting 'command'");
+ return;
+ }
+ parseCommand(confDat->Translator);
+ }
+
+ void parseOptimizer() {
+ if (next() != COMMAND) {
+ error("Expecting 'command'");
+ return;
+ }
+ parseCommand(confDat->Optimizer);
+ }
+
+ void parseAssembler() {
+ if (next() != COMMAND) {
+ error("Expecting 'command'");
+ return;
+ }
+ parseCommand(confDat->Assembler);
+ }
+
+ void parseLinker() {
+ if (next() != COMMAND) {
+ error("Expecting 'command'");
+ return;
+ }
+ parseCommand(confDat->Linker);
+ }
+
+ void parseAssignment() {
+ switch (token) {
+ case LANG: return parseLang();
+ case PREPROCESSOR: return parsePreProcessor();
+ case TRANSLATOR: return parseTranslator();
+ case OPTIMIZER: return parseOptimizer();
+ case ASSEMBLER: return parseAssembler();
+ case LINKER: return parseLinker();
+ case EOLTOK: break; // just ignore
+ case ERRORTOK:
+ default:
+ error("Invalid top level configuration item identifier");
+ }
+ }
+
+ void parseFile() {
+ while ( next() != 0 ) {
+ parseAssignment();
+ }
+ provider->checkErrors();
}
- if (invalidItem)
- provider.error("Invalid configuration item: " + line.substr(stPos, eqPos-stPos));
+ };
+
+ void
+ ParseConfigData(InputProvider& provider, CompilerDriver::ConfigData& confDat) {
+ ParseContext ctxt;
+ ctxt.token = 0;
+ ctxt.provider = &provider;
+ ctxt.confDat = &confDat;
+ ctxt.action = 0;
+ ctxt.parseFile();
}
- return new CompilerDriver::ConfigData(data);
}
CompilerDriver::ConfigData*
-ReadConfigData(const std::string& ftype) {
- if ( ftype == "ll" ) {
- StaticInputProvider sip(LL_Data, sizeof(LL_Data)/sizeof(LL_Data[0]),
- "LLVM Assembly (internal)");
- return ParseConfigData(sip);
- } else if (ftype == "st") {
- StaticInputProvider sip(ST_Data, sizeof(ST_Data)/sizeof(ST_Data[0]),
- "Stacker (internal)");
- return ParseConfigData(sip);
+LLVMC_ConfigDataProvider::ReadConfigData(const std::string& ftype) {
+ CompilerDriver::ConfigData* result = 0;
+ if (configDir.empty()) {
+ FileInputProvider fip( std::string("/etc/llvm/") + ftype );
+ if (!fip.okay()) {
+ fip.error("Configuration for '" + ftype + "' is not available.");
+ fip.checkErrors();
+ }
+ else {
+ result = new CompilerDriver::ConfigData();
+ ParseConfigData(fip,*result);
+ }
+ } else {
+ FileInputProvider fip( configDir + "/" + ftype );
+ if (!fip.okay()) {
+ fip.error("Configuration for '" + ftype + "' is not available.");
+ fip.checkErrors();
+ }
+ else {
+ result = new CompilerDriver::ConfigData();
+ ParseConfigData(fip,*result);
+ }
}
- return 0;
-}
-
+ return result;
}
LLVMC_ConfigDataProvider::LLVMC_ConfigDataProvider()
diff --git a/tools/llvmc/ConfigData.h b/tools/llvmc/ConfigData.h
index f11931d999..e94fb89642 100644
--- a/tools/llvmc/ConfigData.h
+++ b/tools/llvmc/ConfigData.h
@@ -42,6 +42,9 @@ namespace llvm {
/// @brief Allow the configuration directory to be set
virtual void setConfigDir(const std::string& dirName) { configDir = dirName; }
+ private:
+ CompilerDriver::ConfigData* ReadConfigData(const std::string& ftype);
+
/// @}
/// @name Data
/// @{
diff --git a/tools/llvmc/ConfigLexer.h b/tools/llvmc/ConfigLexer.h
new file mode 100644
index 0000000000..5a3e9e9f74
--- /dev/null
+++ b/tools/llvmc/ConfigLexer.h
@@ -0,0 +1,77 @@
+//===- ConfigLexer.h - ConfigLexer Declarations -----------------*- 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 declares the types and data needed by ConfigLexer.l
+//
+//===------------------------------------------------------------------------===
+#ifndef LLVM_TOOLS_LLVMC_CONFIGLEXER_H
+#define LLVM_TOOLS_LLVMC_CONFIGLEXER_H
+
+#include <string>
+#include <istream>
+
+namespace llvm {
+
+struct ConfigLexerInfo
+{
+ int64_t IntegerVal;
+ std::string StringVal;
+};
+
+extern ConfigLexerInfo ConfigLexerData;
+extern unsigned ConfigLexerLine;
+
+class InputProvider {
+ public:
+ InputProvider(const std::string& nm) {
+ name = nm;
+ errCount = 0;
+ }
+ virtual ~InputProvider();
+ virtual unsigned read(char *buf, unsigned max_size) = 0;
+ virtual void error(const std::string& msg);
+ virtual void checkErrors();
+
+ private:
+ std::string name;
+ unsigned errCount;
+};
+
+extern InputProvider* ConfigLexerInput;
+
+enum ConfigLexerTokens {
+ EOFTOK = 0, ///< Returned by Configlex when we hit end of file
+ EOLTOK, ///< End of line
+ ERRORTOK, ///< Error token
+ OPTION, ///< A command line option
+ SEPARATOR, ///< A configuration item separator
+ EQUALS, ///< The equals sign, =
+ TRUETOK, ///< A boolean true value (true/yes/on)
+ FALSETOK, ///< A boolean false value (false/no/off)
+ INTEGER, ///< An integer
+ STRING, ///< A quoted string
+ IN_SUBST, ///< The input substitution item @in@
+ OUT_SUBST, ///< The output substitution item @out@
+ LANG, ///< The item "lang" (and case variants)
+ PREPROCESSOR, ///< The item "preprocessor" (and case variants)
+ TRANSLATOR, ///< The item "translator" (and case variants)
+ OPTIMIZER, ///< The item "optimizer" (and case variants)
+ ASSEMBLER, ///< The item "assembler" (and case variants)
+ LINKER, ///< The item "linker" (and case variants)
+ NAME, ///< The item "name" (and case variants)
+ NEEDED, ///< The item "needed" (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)
+ OPTIMIZES, ///< The item "optimizes" (and case variants)
+};
+
+}
+
+#endif
diff --git a/tools/llvmc/ConfigLexer.l b/tools/llvmc/ConfigLexer.l
new file mode 100644
index 0000000000..58ddd2bdbd
--- /dev/null
+++ b/tools/llvmc/ConfigLexer.l
@@ -0,0 +1,135 @@
+/*===- ConfigLexer.l - Scanner for CompilerDriver Config Files -*- 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 the flex scanner for configuration files for the
+// llvmc CompilerDriver.
+//
+//===----------------------------------------------------------------------===*/
+
+
+%option prefix="Config"
+%option yylineno
+%option nostdinit
+%option never-interactive
+%option batch
+%option noyywrap
+%option nodefault
+%option 8bit
+%option outfile="ConfigLexer.cpp"
+%option ecs
+%option noreject
+%option noyymore
+%array
+
+%{
+
+#include "ConfigLexer.h"
+
+#define YY_INPUT(buf,result,max_size) \
+ { \
+ assert(ConfigLexerInput != 0 && "Oops"); \
+ result = ConfigLexerInput->read(buf,max_size); \
+ if (result == 0 ) result = YY_NULL; \
+ }
+
+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';
+ }
+ return Result;
+}
+
+bool in_value = false;
+
+%}
+
+LANG lang|Lang|LANG
+PREPROCESSOR preprocessor|PreProcessor|PREPROCESSOR
+TRANSLATOR translator|Translator|TRANSLATOR
+OPTIMIZER optimizer|Optimizer|OPTIMIZER
+ASSEMBLER assembler|Assembler|ASSEMBLER
+LINKER linker|Linker|LINKER
+NAME name|Name|NAME
+NEEDED needed|Needed|NEEDED
+COMMAND command|Command|COMMAND
+PREPROCESSES preprocesses|PreProcesses|PREPROCESSES
+GROKS_DASH_O groks_dash_O|Groks_Dash_O|GROKS_DASH_O
+OPTIMIZES optimizes|Optimizes|OPTIMIZES
+Comment \#[^\n]*
+NewLine \n
+White [ \t]*
+Option [-A-Za-z0-9_:%+/\\|,]*
+Sep \.
+Eq \=
+String \"[^\"]*\"
+Integer [-+]?[0-9]+
+True true|True|TRUE
+False false|False|FALSE
+On on|On|ON
+Off off|Off|OFF
+Yes yes|Yes|YES
+No no|No|NO
+
+%%
+
+{NewLine} { in_value = false; ConfigLexerLine++; return EOLTOK; }
+{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; }
+{NEEDED} { if (in_value) { ConfigLexerData.StringVal = "needed";
+ return OPTION; } else return NEEDED; }
+{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; }
+{OPTIMIZES} { if (in_value) { ConfigLexerData.StringVal = "optimizes";
+ return OPTION; } else return OPTIMIZES; }
+{Sep} { if (in_value) { ConfigLexerData.StringVal = yytext;
+ return OPTION; } }
+
+@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; }
+
+{Eq} { in_value = true; return EQUALS; }
+{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
+ return STRING;
+ }
+
+%%
diff --git a/tools/llvmc/Configuration.cpp b/tools/llvmc/Configuration.cpp
index 94949c405d..d2e788bf12 100644
--- a/tools/llvmc/Configuration.cpp
+++ b/tools/llvmc/Configuration.cpp
@@ -13,391 +13,282 @@
//===------------------------------------------------------------------------===
#include "ConfigData.h"
+#include "ConfigLexer.h"
#include "CompilerDriver.h"
#include "Support/StringExtras.h"
#include <iostream>
+#include <fstream>
using namespace llvm;
-namespace {
+extern int ::Configlex();
-// This array of strings provides the input for ".ll" files (LLVM Assembly)
-// to the configuration file parser. This data is just "built-in" to
-// llvmc so it doesn't have to be read from a configuration file.
-static const char* LL_Data[] = {
- "lang.name=LLVM Assembly",
- "lang.translator.preprocesses=false",
- "lang.translator.optimizes=No",
- "lang.translator.groks_dash_O=No",
- "lang.preprocessor.needed=0",
- "preprocessor.prog=",
- "preprocessor.args=",
- "translator.prog=llvm-as",
- "translator.args=@in@ -o @out@",
- "optimizer.prog=opt",
- "optimizer.args=@in@ -o @out@",
- "assembler.prog=llc",
- "assembler.args=@in@ -o @out@",
- "linker.prog=llvm-link",
- "linker.args=@in@ -o @out@"
-};
-
-// This array of strings provides the input for ".st" files (Stacker).
-static const char* ST_Data[] = {
- "lang.name=Stacker",
- "lang.translator.preprocesses=false",
- "lang.translator.optimizes=true",
- "lang.translator.groks_dash_O=0",
- "lang.preprocessor.needed=0",
- "preprocessor.prog=cp",
- "preprocessor.args=@in@ @out@",
- "translator.prog=stkrc",
- "translator.args=@in@ -o @out@ -S 2048",
- "optimizer.prog=opt",
- "optimizer.args=@in@ -o @out@",
- "assembler.prog=llc",
- "assembler.args=@in@ -o @out@",
- "linker.prog=llvm-link",
- "linker.args=@in@ -o @out@"
-};
-
-class InputProvider {
- public:
- virtual bool getLine(std::string& line) = 0;
- virtual void error(const std::string& msg) = 0;
- virtual bool errorOccurred() = 0;
-};
-
-class StaticInputProvider : public InputProvider {
- public:
- StaticInputProvider(const char *data[], size_t count,
- const std::string& nam) {
- TheData = data;
- limit = count;
- where = 0;
- name = nam;
- errCount = 0;
- }
- virtual ~StaticInputProvider() {}
- virtual bool getLine(std::string& line) {
- if ( where >= limit ) return false;
- line = TheData[where++];
- return true;
- }
+namespace llvm {
+ ConfigLexerInfo ConfigLexerData;
+ InputProvider* ConfigLexerInput = 0;
+ unsigned ConfigLexerLine = 1;
- virtual void error(const std::string& msg) {
- std::cerr << name << ":" << where << ": Error: " << msg << "\n";
- errCount++;
+ InputProvider::~InputProvider() {}
+ void InputProvider::error(const std::string& msg) {
+ std::cerr << name << ":" << ConfigLexerLine << ": Error: " << msg << "\n";
+ errCount++;
+ }
+
+ void InputProvider::checkErrors() {
+ if (errCount > 0) {
+ std::cerr << name << " had " << errCount << " errors. Terminating.\n";
+ exit(errCount);
}
+ }
- virtual bool errorOccurred() { return errCount > 0; };
+}
- private:
- const char**TheData;
- size_t limit;
- size_t where;
- std::string name;
- size_t errCount;
-};
+namespace {
-inline bool recognize(const char*& p, const char*token) {
- while (*p == *token && *token != '\0')
- ++token, p++;
- return *token == '\0' && ((*p == '\0') || ( *p == '.' ) || (*p == '='));
-}
+ class FileInputProvider : public InputProvider {
+ public:
+ FileInputProvider(const std::string & fname)
+ : InputProvider(fname)
+ , F(fname.c_str()) {
+ ConfigLexerInput = this;
+ }
+ virtual ~FileInputProvider() { F.close(); ConfigLexerInput = 0; }
+ virtual unsigned read(char *buffer, unsigned max_size) {
+ if (F.good()) {
+ F.read(buffer,max_size);
+ if ( F.gcount() ) return F.gcount() - 1;
+ }
+ return 0;
+ }
+
+ bool okay() { return F.good(); }
+ private:
+ std::ifstream F;
+ };
+
+ struct ParseContext
+ {
+ int token;
+ InputProvider* provider;
+ CompilerDriver::ConfigData* confDat;
+ CompilerDriver::Action* action;
+
+ int next() { return token = Configlex(); }
+
+ bool next_is_real() {
+ token = Configlex();
+ return (token != EOLTOK) && (token != ERRORTOK) && (token != 0);
+ }
-inline bool getBoolean(const std::string& value) {
- switch (value[0]) {
- case 't':
- case 'T':
- case '1':
- case 'y':
- case 'Y':
- return true;
- default :
- return false;
- }
- return false;
-}
+ void eatLineRemnant() {
+ while (next_is_real()) ;
+ }
-inline void skipWhitespace( size_t& pos, const std::string& line ) {
- while (pos < line.size() && (
- line[pos] == ' ' || // Space
- line[pos] == '\t' || // Horizontal Tab
- line[pos] == '\n' || // New Line
- line[pos] == '\v' || // Vertical Tab
- line[pos] == '\f' || // Form Feed
- line[pos] == '\r') // Carriate Return
- )
- pos++;
-}
+ void error(const std::string& msg, bool skip = true) {
+ provider->error(msg);
+ if (skip)
+ eatLineRemnant();
+ }
-inline void parseArgs(CompilerDriver::Action& pat,
- const std::string& value,
- InputProvider& provider )
-{
- const char* p = value.c_str();
- const char* argStart = p;
- while (*p != '\0') {
- switch (*p) {
- case ' ':
- if (argStart != p)
- pat.args.push_back(std::string(argStart, p-argStart));
- argStart = ++p;
- break;
- case '@' :
- {
- if (argStart != p)
- pat.args.push_back(std::string(argStart,p-argStart));
- const char* token = ++p;
- while (*p != '@' && *p != 0)
- p++;
- if ( *p != '@' ) {
- provider.error("Unterminated substitution token");
- return;
- } else {
- p++;
- bool legal = false;
- switch (token[0]) {
- case 'i':
- if (token[1] == 'n' && token[2] == '@' ) {
- pat.inputAt = pat.args.size();
- pat.args.push_back("in");
- legal = true;
- argStart = p;
- }
- break;
- case 'o':
- if (token[1] == 'u' && token[2] == 't' && token[3] == '@') {
- pat.outputAt = pat.args.size();
- pat.args.push_back("out");
- legal = true;
- argStart = p;
- }
- break;
- default:
- break;
- }
- if (!legal) {
- provider.error("Invalid substitution token");
- return;
- }
+ std::string parseName() {
+ std::string result;
+ if (next() == EQUALS) {
+ while (next_is_real()) {
+ switch (token ) {
+ case STRING :
+ case OPTION :
+ result += ConfigLexerData.StringVal + " ";
+ break;
+ default:
+ error("Invalid name");
+ break;
}
}
- break;
- default :
- p++;
- break;
+ if (result.empty())
+ error("Name exepected");
+ else
+ result.erase(result.size()-1,1);
+ } else
+ error("= expected");
+ return result;
}
- }
-}
-CompilerDriver::ConfigData*
-ParseConfigData(InputProvider& provider) {
- std::string line;
- CompilerDriver::ConfigData data;
- while ( provider.getLine(line) ) {
- // Check line length first
- size_t lineLen = line.size();
- if (lineLen > 4096)
- provider.error("length of input line (" + utostr(lineLen) +
- ") is too long");
-
- // First, skip whitespace
- size_t stPos = 0;
- skipWhitespace(stPos, line);
-
- // See if there's a hash mark. It and everything after it is
- // ignored so lets delete that now.
- size_t hashPos = line.find('#');
- if (hashPos != std::string::npos)
- line.erase(hashPos);
-
- // Make sure we have something left to parse
- if (line.size() == 0)
- continue; // ignore full-line comment or whitespace line
-
- // Find the equals sign
- size_t eqPos = line.find('=');
- if (eqPos == std::string::npos)
- provider.error("Configuration directive is missing an =");
-
- // extract the item name
- std::string name(line, stPos, eqPos-stPos);
-
- // directives without names are illegal
- if (name.empty())
- provider.error("Configuration directive name is empty");
-
- // Skip whitespace in the value
- size_t valPos = eqPos + 1;
- skipWhitespace(valPos, line);
-
- // Skip white space at end of value
- size_t endPos = line.length() - 1;
- while (line[endPos] == ' ')
- endPos--;
-
- // extract the item value
- std::string value(line, valPos, endPos-valPos+1);
-
- // Get the configuration item as a char pointer
- const char*p = name.c_str();
-
- // Indicate we haven't found an invalid item yet.
- bool invalidItem = false;
-
- // Parse the contents by examining first character and
- // using the recognize function strategically
- switch (*p++) {
- case 'l' :
- // could it be "lang."
- if (*p == 'a') { // "lang." ?
- if (recognize(p,"ang")) {
- p++;
- switch (*p++) {
- case 'n':
- if (recognize(p,"ame"))
- data.langName = value;
- else
- invalidItem = true;
- break;
- case 't':
- if (recognize(p,"ranslator")) {
- p++;
- if (recognize(p,"preprocesses"))
- data.TranslatorPreprocesses = getBoolean(value);
- else if (recognize(p, "optimizes"))
- data.TranslatorOptimizes = getBoolean(value);
- else if (recognize(p, "groks_dash_O"))
- data.TranslatorGroksDashO = getBoolean(value);
- else
- invalidItem = true;
- }
- else
- invalidItem = true;
- break;
- case 'p':
- if (recognize(p,"reprocessor")) {
- p++;
- if (recognize(p,"needed")) {
- data.PreprocessorNeeded = getBoolean(value);
- } else
- invalidItem = true;
- }
- else
- invalidItem = true;
- break;
-
- default:
- invalidItem = true;
- break;
- }
- }
- } else if (*p == 'i') { // "linker." ?
- if (recognize(p,"inker")) {
- p++;
- if (recognize(p,"prog"))
- data.Linker.program = value;
- else if (recognize(p,"args"))
- parseArgs(data.Linker,value,provider);
- else
- invalidItem = true;
- }
- else
- invalidItem = true;
- } else {
- invalidItem = true;
+ bool parseBoolean() {
+ bool result = true;
+ if (next() == EQUALS) {
+ if (next() == FALSETOK) {
+ result = false;
+ } else if (token != TRUETOK) {
+ error("Expecting boolean value");
+ return false;
}
- break;
-
- case 'p' :
- if (*p == 'r') { // "preprocessor." ?
- if (recognize(p, "reprocessor")) {
- p++;
- if (recognize(p,"prog"))
- data.PreProcessor.program = value;
- else if (recognize(p,"args"))
- parseArgs(data.PreProcessor,value,provider);
- else
- invalidItem = true;
- } else
- invalidItem = true;
- } else {
- invalidItem = true;
+ if (next() != EOLTOK && token != 0) {
+ error("Extraneous tokens after boolean");
}
- break;
-
- case 't' :
- if (*p == 'r') { // "translator." ?
- if (recognize(p, "ranslator")) {
- p++;
- if (recognize(p,"prog"))
- data.Translator.program = value;
- else if (recognize(p,"args"))
- parseArgs(data.Translator,value,provider);
- else
- invalidItem = true;
- } else
- invalidItem = true;
- } else {
- invalidItem = true;
- }
- break;
-
- case 'o' :
- if (*p == 'p') { // "optimizer." ?
- if (recognize(p, "ptimizer")) {
- p++;
- if (recognize(p,"prog"))
- data.Optimizer.program = value;
- else if (recognize(p,"args"))
- parseArgs(data.Optimizer,value,provider);
- else
- invalidItem = true;
- } else
- invalidItem = true;
- } else {
- invalidItem = true;
+ }
+ else
+ error("Expecting '='");
+ return result;
+ }
+
+ void parseLang() {
+ if ( next() == NAME ) {
+ confDat->langName = parseName();
+ } else if (token == TRANSLATOR) {
+ switch (next()) {
+ case PREPROCESSES:
+ confDat->TranslatorPreprocesses = parseBoolean();
+ break;
+ case OPTIMIZES:
+ confDat->TranslatorOptimizes = parseBoolean();
+ break;
+ case GROKS_DASH_O:
+ confDat->TranslatorGroksDashO = parseBoolean();
+ break;
+ default:
+ error("Invalid lang.translator identifier");
+ break;
}
- break;
- case 'a' :
- if (*p == 's') { // "assembler." ?
- if (recognize(p, "ssembler")) {
- p++;
- if (recognize(p,"prog"))
- data.Assembler.program = value;
- else if (recognize(p,"args"))
- parseArgs(data.Assembler,value,provider);
- else
- invalidItem = true;
- } else
- invalidItem = true;
+ }
+ else if (token == PREPROCESSOR) {
+ if (next() == NEEDED)
+ confDat->PreprocessorNeeded = parseBoolean();
+ }
+ else {
+ error("Expecting valid identifier after 'lang.'");
+ }
+ }
+
+ void parseCommand(CompilerDriver::Action& action) {
+ if (next() == EQUALS) {
+ next();
+ if (token == EOLTOK) {
+ // no value (valid)
+ action.program.clear();
+ action.args.clear();
+ action.inputAt = 0;
+ action.outputAt = 0;
} else {
- invalidItem = true;
+ if (token == STRING || token == OPTION) {
+ action.program = ConfigLexerData.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);
+ }
}
- break;
+ }
+ }
+
+ void parsePreProcessor() {
+ if (next() != COMMAND) {
+ error("Expecting 'command'");
+ return;
+ }
+ parseCommand(confDat->PreProcessor);
+ }
+
+ void parseTranslator() {
+ if (next() != COMMAND) {
+ error("Expecting 'command'");
+ return;
+ }
+ parseCommand(confDat->Translator);
+ }
+
+ void parseOptimizer() {
+ if (next() != COMMAND) {
+ error("Expecting 'command'");
+ return;
+ }
+ parseCommand(confDat->Optimizer);
+ }
+
+ void parseAssembler() {
+ if (next() != COMMAND) {
+ error("Expecting 'command'");
+ return;
+ }
+ parseCommand(confDat->Assembler);
+ }
+
+ void parseLinker() {
+ if (next() != COMMAND) {
+ error("Expecting 'command'");
+ return;
+ }
+ parseCommand(confDat->Linker);
+ }
+
+ void parseAssignment() {
+ switch (token) {
+ case LANG: return parseLang();
+ case PREPROCESSOR: return parsePreProcessor();
+ case TRANSLATOR: return parseTranslator();
+ case OPTIMIZER: return parseOptimizer();
+ case ASSEMBLER: return parseAssembler();
+ case LINKER: return parseLinker();
+ case EOLTOK: break; // just ignore
+ case ERRORTOK:
+ default:
+ error("Invalid top level configuration item identifier");
+ }
+ }
+
+ void parseFile() {
+ while ( next() != 0 ) {
+ parseAssignment();
+ }
+ provider->checkErrors();
}
- if (invalidItem)
- provider.error("Invalid configuration item: " + line.substr(stPos, eqPos-stPos));
+ };
+
+ void
+ ParseConfigData(InputProvider& provider, CompilerDriver::ConfigData& confDat) {
+ ParseContext ctxt;
+ ctxt.token = 0;
+ ctxt.provider = &provider;
+ ctxt.confDat = &confDat;
+ ctxt.action = 0;
+ ctxt.parseFile();
}
- return new CompilerDriver::ConfigData(data);
}
CompilerDriver::ConfigData*
-ReadConfigData(const std::string& ftype) {
- if ( ftype == "ll" ) {
- StaticInputProvider sip(LL_Data, sizeof(LL_Data)/sizeof(LL_Data[0]),
- "LLVM Assembly (internal)");
- return ParseConfigData(sip);
- } else if (ftype == "st") {
- StaticInputProvider sip(ST_Data, sizeof(ST_Data)/sizeof(ST_Data[0]),
- "Stacker (internal)");
- return ParseConfigData(sip);
+LLVMC_ConfigDataProvider::ReadConfigData(const std::string& ftype) {
+ CompilerDriver::ConfigData* result = 0;
+ if (configDir.empty()) {
+ FileInputProvider fip( std::string("/etc/llvm/") + ftype );
+ if (!fip.okay()) {
+ fip.error("Configuration for '" + ftype + "' is not available.");
+ fip.checkErrors();
+ }
+ else {
+ result = new CompilerDriver::ConfigData();
+ ParseConfigData(fip,*result);
+ }
+ } else {
+ FileInputProvider fip( configDir + "/" + ftype );
+ if (!fip.okay()) {
+ fip.error("Configuration for '" + ftype + "' is not available.");
+ fip.checkErrors();
+ }
+ else {
+ result = new CompilerDriver::ConfigData();
+ ParseConfigData(fip,*result);
+ }
}
- return 0;
-}
-
+ return result;
}
LLVMC_ConfigDataProvider::LLVMC_ConfigDataProvider()
diff --git a/tools/llvmc/Configuration.h b/tools/llvmc/Configuration.h
index f11931d999..e94fb89642 100644
--- a/tools/llvmc/Configuration.h
+++ b/tools/llvmc/Configuration.h
@@ -42,6 +42,9 @@ namespace llvm {
/// @brief Allow the configuration directory to be set
virtual void setConfigDir(const std::string& dirName) { configDir = dirName; }
+ private:
+ CompilerDriver::ConfigData* ReadConfigData(const std::string& ftype);
+
/// @}
/// @name Data
/// @{
diff --git a/tools/llvmc/llvmc.cpp b/tools/llvmc/llvmc.cpp
index 878fb65e0c..9cf43cb3ff 100644
--- a/tools/llvmc/llvmc.cpp
+++ b/tools/llvmc/llvmc.cpp
@@ -207,6 +207,7 @@ int main(int argc, char **argv) {
// Construct the ConfigDataProvider object
LLVMC_ConfigDataProvider Provider;
+ Provider.setConfigDir(ConfigDir);
// Construct the CompilerDriver object
CompilerDriver CD(Provider);