diff options
author | Dan Gohman <djg@cray.com> | 2007-07-18 16:29:46 +0000 |
---|---|---|
committer | Dan Gohman <djg@cray.com> | 2007-07-18 16:29:46 +0000 |
commit | f17a25c88b892d30c2b41ba7ecdfbdfb2b4be9cc (patch) | |
tree | ebb79ea1ee5e3bc1fdf38541a811a8b804f0679a /tools/llvmc/Configuration.cpp | |
download | external_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.cpp | 633 |
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 +} |