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
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
+}