From 2594c9abbf1301d204782cbab1a0a4e392ddbe88 Mon Sep 17 00:00:00 2001 From: Reid Spencer Date: Fri, 13 Aug 2004 20:21:22 +0000 Subject: 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 --- tools/llvmc/ConfigData.cpp | 441 ++++++++++++++++++++++++++++++++++++++++++ tools/llvmc/ConfigData.h | 58 ++++++ tools/llvmc/Configuration.cpp | 441 ++++++++++++++++++++++++++++++++++++++++++ tools/llvmc/Configuration.h | 58 ++++++ 4 files changed, 998 insertions(+) create mode 100644 tools/llvmc/ConfigData.cpp create mode 100644 tools/llvmc/ConfigData.h create mode 100644 tools/llvmc/Configuration.cpp create mode 100644 tools/llvmc/Configuration.h (limited to 'tools/llvmc') 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 + +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 + +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::equal_to > 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 + +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 + +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::equal_to > ConfigDataMap; + ConfigDataMap Configurations; ///< The cache of configurations + std::string configDir; + /// @} + }; +} + +#endif -- cgit v1.2.3