aboutsummaryrefslogtreecommitdiffstats
path: root/tools/llvmc/Configuration.cpp
diff options
context:
space:
mode:
authorDan Gohman <djg@cray.com>2007-07-18 16:29:46 +0000
committerDan Gohman <djg@cray.com>2007-07-18 16:29:46 +0000
commitf17a25c88b892d30c2b41ba7ecdfbdfb2b4be9cc (patch)
treeebb79ea1ee5e3bc1fdf38541a811a8b804f0679a /tools/llvmc/Configuration.cpp
downloadexternal_llvm-f17a25c88b892d30c2b41ba7ecdfbdfb2b4be9cc.zip
external_llvm-f17a25c88b892d30c2b41ba7ecdfbdfb2b4be9cc.tar.gz
external_llvm-f17a25c88b892d30c2b41ba7ecdfbdfb2b4be9cc.tar.bz2
It's not necessary to do rounding for alloca operations when the requested
alignment is equal to the stack alignment. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@40004 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvmc/Configuration.cpp')
-rw-r--r--tools/llvmc/Configuration.cpp633
1 files changed, 633 insertions, 0 deletions
diff --git a/tools/llvmc/Configuration.cpp b/tools/llvmc/Configuration.cpp
new file mode 100644
index 0000000..aafca79
--- /dev/null
+++ b/tools/llvmc/Configuration.cpp
@@ -0,0 +1,633 @@
+//===- Configuration.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 "Configuration.h"
+#include "ConfigLexer.h"
+#include "CompilerDriver.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/ADT/StringExtras.h"
+#include <iostream>
+#include <fstream>
+
+using namespace llvm;
+
+namespace sys {
+ // From CompilerDriver.cpp (for now)
+ extern bool FileIsReadable(const std::string& fname);
+}
+
+namespace llvm {
+ ConfigLexerInfo ConfigLexerState;
+ InputProvider* ConfigLexerInput = 0;
+
+ InputProvider::~InputProvider() {}
+ void InputProvider::error(const std::string& msg) {
+ std::cerr << name << ":" << ConfigLexerState.lineNum << ": Error: " <<
+ msg << "\n";
+ errCount++;
+ }
+
+ void InputProvider::checkErrors() {
+ if (errCount > 0) {
+ std::cerr << name << " had " << errCount << " errors. Terminating.\n";
+ exit(errCount);
+ }
+ }
+
+}
+
+namespace {
+
+ 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;
+ };
+
+ cl::opt<bool> DumpTokens("dump-tokens", cl::Optional, cl::Hidden,
+ cl::init(false), cl::desc("Dump lexical tokens (debug use only)."));
+
+ struct Parser
+ {
+ Parser() {
+ token = EOFTOK;
+ provider = 0;
+ confDat = 0;
+ ConfigLexerState.lineNum = 1;
+ ConfigLexerState.in_value = false;
+ ConfigLexerState.StringVal.clear();
+ ConfigLexerState.IntegerVal = 0;
+ };
+
+ ConfigLexerTokens token;
+ InputProvider* provider;
+ CompilerDriver::ConfigData* confDat;
+
+ inline int next() {
+ token = Configlex();
+ if (DumpTokens)
+ std::cerr << token << "\n";
+ return token;
+ }
+
+ inline bool next_is_real() {
+ next();
+ return (token != EOLTOK) && (token != ERRORTOK) && (token != 0);
+ }
+
+ inline void eatLineRemnant() {
+ while (next_is_real()) ;
+ }
+
+ void error(const std::string& msg, bool skip = true) {
+ provider->error(msg);
+ if (skip)
+ eatLineRemnant();
+ }
+
+ bool parseCompleteItem(std::string& result) {
+ result.clear();
+ while (next_is_real()) {
+ switch (token ) {
+ case LLVMGCCDIR_SUBST:
+ case LLVMGCCARCH_SUBST:
+ case STRING :
+ case OPTION :
+ result += ConfigLexerState.StringVal;
+ break;
+ case SEPARATOR:
+ result += ".";
+ break;
+ case SPACE:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+ }
+
+ std::string parseName() {
+ std::string result;
+ if (next() == EQUALS) {
+ if (parseCompleteItem(result))
+ eatLineRemnant();
+ if (result.empty())
+ error("Name exepected");
+ } else
+ error("Expecting '='");
+ return result;
+ }
+
+ bool parseBoolean() {
+ bool result = true;
+ if (next() == EQUALS) {
+ if (next() == SPACE)
+ next();
+ if (token == FALSETOK) {
+ result = false;
+ } else if (token != TRUETOK) {
+ error("Expecting boolean value");
+ return false;
+ }
+ if (next() != EOLTOK && token != 0) {
+ error("Extraneous tokens after boolean");
+ }
+ }
+ else
+ error("Expecting '='");
+ return result;
+ }
+
+ bool parseSubstitution(CompilerDriver::StringVector& optList) {
+ switch (token) {
+ case ARGS_SUBST: optList.push_back("%args%"); break;
+ case BINDIR_SUBST: optList.push_back("%bindir%"); break;
+ case DEFS_SUBST: optList.push_back("%defs%"); break;
+ case IN_SUBST: optList.push_back("%in%"); break;
+ case INCLS_SUBST: optList.push_back("%incls%"); break;
+ case LIBDIR_SUBST: optList.push_back("%libdir%"); break;
+ case LIBS_SUBST: optList.push_back("%libs%"); break;
+ case OPT_SUBST: optList.push_back("%opt%"); break;
+ case OUT_SUBST: optList.push_back("%out%"); break;
+ case TARGET_SUBST: optList.push_back("%target%"); break;
+ case STATS_SUBST: optList.push_back("%stats%"); break;
+ case TIME_SUBST: optList.push_back("%time%"); break;
+ case VERBOSE_SUBST: optList.push_back("%verbose%"); break;
+ case FOPTS_SUBST: optList.push_back("%fOpts%"); break;
+ case MOPTS_SUBST: optList.push_back("%Mopts%"); break;
+ case WOPTS_SUBST: optList.push_back("%Wopts%"); break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ void parseOptionList(CompilerDriver::StringVector& optList ) {
+ if (next() == EQUALS) {
+ while (next_is_real()) {
+ if (token == STRING || token == OPTION)
+ optList.push_back(ConfigLexerState.StringVal);
+ else if (!parseSubstitution(optList)) {
+ error("Expecting a program argument or substitution", false);
+ break;
+ }
+ }
+ } else
+ error("Expecting '='");
+ }
+
+ void parseVersion() {
+ if (next() != EQUALS)
+ error("Expecting '='");
+ while (next_is_real()) {
+ if (token == STRING || token == OPTION)
+ confDat->version = ConfigLexerState.StringVal;
+ else
+ error("Expecting a version string");
+ }
+ }
+
+ void parseLibs() {
+ if (next() != EQUALS)
+ error("Expecting '='");
+ std::string lib;
+ while (parseCompleteItem(lib)) {
+ if (!lib.empty()) {
+ confDat->libpaths.push_back(lib);
+ }
+ }
+ }
+
+ void parseLang() {
+ if (next() != SEPARATOR)
+ error("Expecting '.'");
+ switch (next() ) {
+ case LIBS:
+ parseLibs();
+ break;
+ case NAME:
+ confDat->langName = parseName();
+ break;
+ case OPT1:
+ parseOptionList(confDat->opts[CompilerDriver::OPT_FAST_COMPILE]);
+ break;
+ case OPT2:
+ parseOptionList(confDat->opts[CompilerDriver::OPT_SIMPLE]);
+ break;
+ case OPT3:
+ parseOptionList(confDat->opts[CompilerDriver::OPT_AGGRESSIVE]);
+ break;
+ case OPT4:
+ parseOptionList(confDat->opts[CompilerDriver::OPT_LINK_TIME]);
+ break;
+ case OPT5:
+ parseOptionList(
+ confDat->opts[CompilerDriver::OPT_AGGRESSIVE_LINK_TIME]);
+ break;
+ default:
+ error("Expecting 'name' or 'optN' after 'lang.'");
+ break;
+ }
+ }
+
+ bool parseProgramName(std::string& str) {
+ str.clear();
+ do {
+ switch (token) {
+ case BINDIR_SUBST:
+ case LLVMGCC_SUBST:
+ case LLVMGXX_SUBST:
+ case LLVMCC1_SUBST:
+ case LLVMCC1PLUS_SUBST:
+ case OPTION:
+ case STRING:
+ case ARGS_SUBST:
+ case DEFS_SUBST:
+ case IN_SUBST:
+ case INCLS_SUBST:
+ case LIBS_SUBST:
+ case OPT_SUBST:
+ case OUT_SUBST:
+ case STATS_SUBST:
+ case TARGET_SUBST:
+ case TIME_SUBST:
+ case VERBOSE_SUBST:
+ case FOPTS_SUBST:
+ case MOPTS_SUBST:
+ case WOPTS_SUBST:
+ str += ConfigLexerState.StringVal;
+ break;
+ case SEPARATOR:
+ str += ".";
+ break;
+ case ASSEMBLY:
+ str += "assembly";
+ break;
+ case BITCODE:
+ str += "bitcode";
+ break;
+ case TRUETOK:
+ str += "true";
+ break;
+ case FALSETOK:
+ str += "false";
+ break;
+ default:
+ break;
+ }
+ next();
+ } while (token != SPACE && token != EOFTOK && token != EOLTOK &&
+ token != ERRORTOK);
+ return !str.empty();
+ }
+
+ void parseCommand(CompilerDriver::Action& action) {
+ if (next() != EQUALS)
+ error("Expecting '='");
+ switch (next()) {
+ case EOLTOK:
+ // no value (valid)
+ action.program.clear();
+ action.args.clear();
+ break;
+ case SPACE:
+ next();
+ /* FALL THROUGH */
+ default:
+ {
+ std::string progname;
+ if (parseProgramName(progname))
+ action.program.set(progname);
+ else
+ error("Expecting a program name");
+
+ // Get the options
+ std::string anOption;
+ while (next_is_real()) {
+ switch (token) {
+ case STRING:
+ case OPTION:
+ anOption += ConfigLexerState.StringVal;
+ break;
+ case ASSEMBLY:
+ anOption += "assembly";
+ break;
+ case BITCODE:
+ anOption += "bitcode";
+ break;
+ case TRUETOK:
+ anOption += "true";
+ break;
+ case FALSETOK:
+ anOption += "false";
+ break;
+ case SEPARATOR:
+ anOption += ".";
+ break;
+ case SPACE:
+ action.args.push_back(anOption);
+ anOption.clear();
+ break;
+ default:
+ if (!parseSubstitution(action.args))
+ error("Expecting a program argument or substitution", false);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ void parsePreprocessor() {
+ if (next() != SEPARATOR)
+ error("Expecting '.'");
+ switch (next()) {
+ case COMMAND:
+ parseCommand(confDat->PreProcessor);
+ break;
+ case REQUIRED:
+ if (parseBoolean())
+ confDat->PreProcessor.set(CompilerDriver::REQUIRED_FLAG);
+ else
+ confDat->PreProcessor.clear(CompilerDriver::REQUIRED_FLAG);
+ break;
+ default:
+ error("Expecting 'command' or 'required' but found '" +
+ ConfigLexerState.StringVal);
+ break;
+ }
+ }
+
+ bool parseOutputFlag() {
+ if (next() == EQUALS) {
+ if (next() == SPACE)
+ next();
+ if (token == ASSEMBLY) {
+ return true;
+ } else if (token == BITCODE) {
+ return false;
+ } else {
+ error("Expecting output type value");
+ return false;
+ }
+ if (next() != EOLTOK && token != 0) {
+ error("Extraneous tokens after output value");
+ }
+ }
+ else
+ error("Expecting '='");
+ return false;
+ }
+
+ void parseTranslator() {
+ if (next() != SEPARATOR)
+ error("Expecting '.'");
+ switch (next()) {
+ case COMMAND:
+ parseCommand(confDat->Translator);
+ break;
+ case REQUIRED:
+ if (parseBoolean())
+ confDat->Translator.set(CompilerDriver::REQUIRED_FLAG);
+ else
+ confDat->Translator.clear(CompilerDriver::REQUIRED_FLAG);
+ break;
+ case PREPROCESSES:
+ if (parseBoolean())
+ confDat->Translator.set(CompilerDriver::PREPROCESSES_FLAG);
+ else
+ confDat->Translator.clear(CompilerDriver::PREPROCESSES_FLAG);
+ break;
+ case OUTPUT:
+ if (parseOutputFlag())
+ confDat->Translator.set(CompilerDriver::OUTPUT_IS_ASM_FLAG);
+ else
+ confDat->Translator.clear(CompilerDriver::OUTPUT_IS_ASM_FLAG);
+ break;
+
+ default:
+ error("Expecting 'command', 'required', 'preprocesses', or "
+ "'output' but found '" + ConfigLexerState.StringVal +
+ "' instead");
+ break;
+ }
+ }
+
+ void parseOptimizer() {
+ if (next() != SEPARATOR)
+ error("Expecting '.'");
+ switch (next()) {
+ case COMMAND:
+ parseCommand(confDat->Optimizer);
+ break;
+ case PREPROCESSES:
+ if (parseBoolean())
+ confDat->Optimizer.set(CompilerDriver::PREPROCESSES_FLAG);
+ else
+ confDat->Optimizer.clear(CompilerDriver::PREPROCESSES_FLAG);
+ break;
+ case TRANSLATES:
+ if (parseBoolean())
+ confDat->Optimizer.set(CompilerDriver::TRANSLATES_FLAG);
+ else
+ confDat->Optimizer.clear(CompilerDriver::TRANSLATES_FLAG);
+ break;
+ case REQUIRED:
+ if (parseBoolean())
+ confDat->Optimizer.set(CompilerDriver::REQUIRED_FLAG);
+ else
+ confDat->Optimizer.clear(CompilerDriver::REQUIRED_FLAG);
+ break;
+ case OUTPUT:
+ if (parseOutputFlag())
+ confDat->Translator.set(CompilerDriver::OUTPUT_IS_ASM_FLAG);
+ else
+ confDat->Translator.clear(CompilerDriver::OUTPUT_IS_ASM_FLAG);
+ break;
+ default:
+ error(std::string("Expecting 'command', 'preprocesses', "
+ "'translates' or 'output' but found '") +
+ ConfigLexerState.StringVal + "' instead");
+ break;
+ }
+ }
+
+ void parseAssembler() {
+ if (next() != SEPARATOR)
+ error("Expecting '.'");
+ switch(next()) {
+ case COMMAND:
+ parseCommand(confDat->Assembler);
+ break;
+ default:
+ error("Expecting 'command'");
+ break;
+ }
+ }
+
+ void parseLinker() {
+ if (next() != SEPARATOR)
+ error("Expecting '.'");
+ switch(next()) {
+ case LIBS:
+ break; //FIXME
+ case LIBPATHS:
+ break; //FIXME
+ default:
+ error("Expecting 'libs' or 'libpaths'");
+ break;
+ }
+ }
+
+ void parseAssignment() {
+ switch (token) {
+ case VERSION_TOK: parseVersion(); break;
+ case LANG: parseLang(); break;
+ case PREPROCESSOR: parsePreprocessor(); break;
+ case TRANSLATOR: parseTranslator(); break;
+ case OPTIMIZER: parseOptimizer(); break;
+ case ASSEMBLER: parseAssembler(); break;
+ case LINKER: parseLinker(); break;
+ case EOLTOK: break; // just ignore
+ case ERRORTOK:
+ default:
+ error("Invalid top level configuration item");
+ break;
+ }
+ }
+
+ void parseFile() {
+ while ( next() != EOFTOK ) {
+ if (token == ERRORTOK)
+ error("Invalid token");
+ else if (token != EOLTOK)
+ parseAssignment();
+ }
+ provider->checkErrors();
+ }
+ };
+
+void
+ParseConfigData(InputProvider& provider, CompilerDriver::ConfigData& confDat) {
+ Parser p;
+ p.token = EOFTOK;
+ p.provider = &provider;
+ p.confDat = &confDat;
+ p.parseFile();
+ }
+
+}
+
+CompilerDriver::ConfigData*
+LLVMC_ConfigDataProvider::ReadConfigData(const std::string& ftype) {
+ CompilerDriver::ConfigData* result = 0;
+ sys::Path confFile;
+ if (configDir.isEmpty()) {
+ // Try the environment variable
+ const char* conf = getenv("LLVM_CONFIG_DIR");
+ if (conf) {
+ confFile.set(conf);
+ confFile.appendComponent(ftype);
+ if (!confFile.canRead())
+ throw std::string("Configuration file for '") + ftype +
+ "' is not available.";
+ } else {
+ // Try the user's home directory
+ confFile = sys::Path::GetUserHomeDirectory();
+ if (!confFile.isEmpty()) {
+ confFile.appendComponent(".llvm");
+ confFile.appendComponent("etc");
+ confFile.appendComponent(ftype);
+ if (!confFile.canRead())
+ confFile.clear();
+ }
+ if (confFile.isEmpty()) {
+ // Okay, try the LLVM installation directory
+ confFile = sys::Path::GetLLVMConfigDir();
+ confFile.appendComponent(ftype);
+ if (!confFile.canRead()) {
+ // Okay, try the "standard" place
+ confFile = sys::Path::GetLLVMDefaultConfigDir();
+ confFile.appendComponent(ftype);
+ if (!confFile.canRead()) {
+ throw std::string("Configuration file for '") + ftype +
+ "' is not available.";
+ }
+ }
+ }
+ }
+ } else {
+ confFile = configDir;
+ confFile.appendComponent(ftype);
+ if (!confFile.canRead())
+ throw std::string("Configuration file for '") + ftype +
+ "' is not available.";
+ }
+ FileInputProvider fip( confFile.toString() );
+ if (!fip.okay()) {
+ throw std::string("Configuration file for '") + ftype +
+ "' is not available.";
+ }
+ result = new CompilerDriver::ConfigData();
+ ParseConfigData(fip,*result);
+ return result;
+}
+
+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
+}