summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorReid Spencer <rspencer@reidspencer.com>2004-08-13 20:21:22 +0000
committerReid Spencer <rspencer@reidspencer.com>2004-08-13 20:21:22 +0000
commit2594c9abbf1301d204782cbab1a0a4e392ddbe88 (patch)
tree5431c57ecbaa8d6da442cf3f90c42c8b00f478eb /tools
parent2c8ab588d5b8ebdee2431df200ce27edc2928174 (diff)
downloadllvm-2594c9abbf1301d204782cbab1a0a4e392ddbe88.tar.gz
llvm-2594c9abbf1301d204782cbab1a0a4e392ddbe88.tar.bz2
llvm-2594c9abbf1301d204782cbab1a0a4e392ddbe88.tar.xz
First version of a utility internal to llvmc that handles the parsing and
construction of configuration data for compiler front ends. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15727 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r--tools/llvmc/ConfigData.cpp441
-rw-r--r--tools/llvmc/ConfigData.h58
-rw-r--r--tools/llvmc/Configuration.cpp441
-rw-r--r--tools/llvmc/Configuration.h58
4 files changed, 998 insertions, 0 deletions
diff --git a/tools/llvmc/ConfigData.cpp b/tools/llvmc/ConfigData.cpp
new file mode 100644
index 0000000000..94949c405d
--- /dev/null
+++ b/tools/llvmc/ConfigData.cpp
@@ -0,0 +1,441 @@
+//===- ConfigData.cpp - Configuration Data Mgmt -----------------*- 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 parsing of configuration files for the LLVM Compiler
+// Driver (llvmc).
+//
+//===------------------------------------------------------------------------===
+
+#include "ConfigData.h"
+#include "CompilerDriver.h"
+#include "Support/StringExtras.h"
+#include <iostream>
+
+using namespace llvm;
+
+namespace {
+
+// 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;
+ }
+
+ virtual void error(const std::string& msg) {
+ std::cerr << name << ":" << where << ": Error: " << msg << "\n";
+ errCount++;
+ }
+
+ virtual bool errorOccurred() { return errCount > 0; };
+
+ private:
+ const char**TheData;
+ size_t limit;
+ size_t where;
+ std::string name;
+ size_t errCount;
+};
+
+inline bool recognize(const char*& p, const char*token) {
+ while (*p == *token && *token != '\0')
+ ++token, p++;
+ return *token == '\0' && ((*p == '\0') || ( *p == '.' ) || (*p == '='));
+}
+
+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;
+}
+
+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++;
+}
+
+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;
+ }
+ }
+ }
+ break;
+ default :
+ p++;
+ break;
+ }
+ }
+}
+
+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;
+ }
+ 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;
+ }
+ 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;
+ }
+ 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 {
+ invalidItem = true;
+ }
+ break;
+ }
+ if (invalidItem)
+ provider.error("Invalid configuration item: " + line.substr(stPos, eqPos-stPos));
+ }
+ 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);
+ }
+ return 0;
+}
+
+}
+
+LLVMC_ConfigDataProvider::LLVMC_ConfigDataProvider()
+ : Configurations()
+ , configDir()
+{
+ Configurations.clear();
+}
+
+LLVMC_ConfigDataProvider::~LLVMC_ConfigDataProvider()
+{
+ ConfigDataMap::iterator cIt = Configurations.begin();
+ while (cIt != Configurations.end()) {
+ CompilerDriver::ConfigData* cd = cIt->second;
+ ++cIt;
+ delete cd;
+ }
+ Configurations.clear();
+}
+
+CompilerDriver::ConfigData*
+LLVMC_ConfigDataProvider::ProvideConfigData(const std::string& filetype) {
+ CompilerDriver::ConfigData* result = 0;
+ if (!Configurations.empty()) {
+ ConfigDataMap::iterator cIt = Configurations.find(filetype);
+ if ( cIt != Configurations.end() ) {
+ // We found one in the case, return it.
+ result = cIt->second;
+ }
+ }
+ if (result == 0) {
+ // The configuration data doesn't exist, we have to go read it.
+ result = ReadConfigData(filetype);
+ // If we got one, cache it
+ if ( result != 0 )
+ Configurations.insert(std::make_pair(filetype,result));
+ }
+ return result; // Might return 0
+}
+
+// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab
diff --git a/tools/llvmc/ConfigData.h b/tools/llvmc/ConfigData.h
new file mode 100644
index 0000000000..f11931d999
--- /dev/null
+++ b/tools/llvmc/ConfigData.h
@@ -0,0 +1,58 @@
+//===- ConfigData.h - Configuration Data Provider ---------------*- 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 LLVMC_ConfigDataProvider class which implements the
+// generation of ConfigData objects for the CompilerDriver.
+//
+//===------------------------------------------------------------------------===
+#ifndef LLVM_TOOLS_LLVMC_CONFIGDATA_H
+#define LLVM_TOOLS_LLVMC_CONFIGDATA_H
+
+#include "CompilerDriver.h"
+#include <Support/hash_map>
+
+namespace llvm {
+ /// This class provides the high level interface to the LLVM Compiler Driver.
+ /// The driver's purpose is to make it easier for compiler writers and users
+ /// of LLVM to utilize the compiler toolkits and LLVM toolset by learning only
+ /// the interface of one program (llvmc).
+ ///
+ /// @see llvmc.cpp
+ /// @brief The interface to the LLVM Compiler Driver.
+ class LLVMC_ConfigDataProvider : public CompilerDriver::ConfigDataProvider {
+ /// @name Constructor
+ /// @{
+ public:
+ LLVMC_ConfigDataProvider();
+ virtual ~LLVMC_ConfigDataProvider();
+
+ /// @name Methods
+ /// @{
+ public:
+ /// @brief Provide the configuration data to the CompilerDriver.
+ virtual CompilerDriver::ConfigData*
+ ProvideConfigData(const std::string& filetype);
+
+ /// @brief Allow the configuration directory to be set
+ virtual void setConfigDir(const std::string& dirName) { configDir = dirName; }
+
+ /// @}
+ /// @name Data
+ /// @{
+ private:
+ /// @brief This type is used internally to hold the configuration data.
+ typedef hash_map<std::string,CompilerDriver::ConfigData*,
+ hash<std::string>,std::equal_to<std::string> > ConfigDataMap;
+ ConfigDataMap Configurations; ///< The cache of configurations
+ std::string configDir;
+ /// @}
+ };
+}
+
+#endif
diff --git a/tools/llvmc/Configuration.cpp b/tools/llvmc/Configuration.cpp
new file mode 100644
index 0000000000..94949c405d
--- /dev/null
+++ b/tools/llvmc/Configuration.cpp
@@ -0,0 +1,441 @@
+//===- ConfigData.cpp - Configuration Data Mgmt -----------------*- 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 parsing of configuration files for the LLVM Compiler
+// Driver (llvmc).
+//
+//===------------------------------------------------------------------------===
+
+#include "ConfigData.h"
+#include "CompilerDriver.h"
+#include "Support/StringExtras.h"
+#include <iostream>
+
+using namespace llvm;
+
+namespace {
+
+// 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;
+ }
+
+ virtual void error(const std::string& msg) {
+ std::cerr << name << ":" << where << ": Error: " << msg << "\n";
+ errCount++;
+ }
+
+ virtual bool errorOccurred() { return errCount > 0; };
+
+ private:
+ const char**TheData;
+ size_t limit;
+ size_t where;
+ std::string name;
+ size_t errCount;
+};
+
+inline bool recognize(const char*& p, const char*token) {
+ while (*p == *token && *token != '\0')
+ ++token, p++;
+ return *token == '\0' && ((*p == '\0') || ( *p == '.' ) || (*p == '='));
+}
+
+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;
+}
+
+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++;
+}
+
+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;
+ }
+ }
+ }
+ break;
+ default :
+ p++;
+ break;
+ }
+ }
+}
+
+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;
+ }
+ 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;
+ }
+ 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;
+ }
+ 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 {
+ invalidItem = true;
+ }
+ break;
+ }
+ if (invalidItem)
+ provider.error("Invalid configuration item: " + line.substr(stPos, eqPos-stPos));
+ }
+ 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);
+ }
+ return 0;
+}
+
+}
+
+LLVMC_ConfigDataProvider::LLVMC_ConfigDataProvider()
+ : Configurations()
+ , configDir()
+{
+ Configurations.clear();
+}
+
+LLVMC_ConfigDataProvider::~LLVMC_ConfigDataProvider()
+{
+ ConfigDataMap::iterator cIt = Configurations.begin();
+ while (cIt != Configurations.end()) {
+ CompilerDriver::ConfigData* cd = cIt->second;
+ ++cIt;
+ delete cd;
+ }
+ Configurations.clear();
+}
+
+CompilerDriver::ConfigData*
+LLVMC_ConfigDataProvider::ProvideConfigData(const std::string& filetype) {
+ CompilerDriver::ConfigData* result = 0;
+ if (!Configurations.empty()) {
+ ConfigDataMap::iterator cIt = Configurations.find(filetype);
+ if ( cIt != Configurations.end() ) {
+ // We found one in the case, return it.
+ result = cIt->second;
+ }
+ }
+ if (result == 0) {
+ // The configuration data doesn't exist, we have to go read it.
+ result = ReadConfigData(filetype);
+ // If we got one, cache it
+ if ( result != 0 )
+ Configurations.insert(std::make_pair(filetype,result));
+ }
+ return result; // Might return 0
+}
+
+// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab
diff --git a/tools/llvmc/Configuration.h b/tools/llvmc/Configuration.h
new file mode 100644
index 0000000000..f11931d999
--- /dev/null
+++ b/tools/llvmc/Configuration.h
@@ -0,0 +1,58 @@
+//===- ConfigData.h - Configuration Data Provider ---------------*- 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 LLVMC_ConfigDataProvider class which implements the
+// generation of ConfigData objects for the CompilerDriver.
+//
+//===------------------------------------------------------------------------===
+#ifndef LLVM_TOOLS_LLVMC_CONFIGDATA_H
+#define LLVM_TOOLS_LLVMC_CONFIGDATA_H
+
+#include "CompilerDriver.h"
+#include <Support/hash_map>
+
+namespace llvm {
+ /// This class provides the high level interface to the LLVM Compiler Driver.
+ /// The driver's purpose is to make it easier for compiler writers and users
+ /// of LLVM to utilize the compiler toolkits and LLVM toolset by learning only
+ /// the interface of one program (llvmc).
+ ///
+ /// @see llvmc.cpp
+ /// @brief The interface to the LLVM Compiler Driver.
+ class LLVMC_ConfigDataProvider : public CompilerDriver::ConfigDataProvider {
+ /// @name Constructor
+ /// @{
+ public:
+ LLVMC_ConfigDataProvider();
+ virtual ~LLVMC_ConfigDataProvider();
+
+ /// @name Methods
+ /// @{
+ public:
+ /// @brief Provide the configuration data to the CompilerDriver.
+ virtual CompilerDriver::ConfigData*
+ ProvideConfigData(const std::string& filetype);
+
+ /// @brief Allow the configuration directory to be set
+ virtual void setConfigDir(const std::string& dirName) { configDir = dirName; }
+
+ /// @}
+ /// @name Data
+ /// @{
+ private:
+ /// @brief This type is used internally to hold the configuration data.
+ typedef hash_map<std::string,CompilerDriver::ConfigData*,
+ hash<std::string>,std::equal_to<std::string> > ConfigDataMap;
+ ConfigDataMap Configurations; ///< The cache of configurations
+ std::string configDir;
+ /// @}
+ };
+}
+
+#endif