Introduce CompilerConfig.

CompilerConfig defines the "attributes" of a Compiler. It contains
target information, configuration, etc. to setup an instance of
Compiler (more specifically, a instance of LLVM TargetMachine used by
the compiler.)

CompilerConfig together with bcc::init::Initialize() will replace
current Compiler::GlobalInitialization().
diff --git a/Config.h b/Config.h
index c1f4133..3c29c60 100644
--- a/Config.h
+++ b/Config.h
@@ -58,14 +58,19 @@
   #endif
 #endif
 
+#define DEFAULT_ARM_TRIPLE_STRING      "armv7-none-linux-gnueabi"
+#define DEFAULT_MIPS_TRIPLE_STRING     "mipsel-none-linux-gnueabi"
+#define DEFAULT_X86_TRIPLE_STRING      "i686-unknown-linux"
+#define DEFAULT_X86_64_TRIPLE_STRING   "x86_64-unknown-linux"
+
 #if defined(DEFAULT_ARM_CODEGEN)
-  #define DEFAULT_TARGET_TRIPLE_STRING "armv7-none-linux-gnueabi"
+  #define DEFAULT_TARGET_TRIPLE_STRING DEFAULT_ARM_TRIPLE_STRING
 #elif defined(DEFAULT_MIPS_CODEGEN)
-  #define DEFAULT_TARGET_TRIPLE_STRING "mipsel-none-linux-gnueabi"
+  #define DEFAULT_TARGET_TRIPLE_STRING DEFAULT_MIPS_TRIPLE_STRING
 #elif defined(DEFAULT_X86_CODEGEN)
-  #define DEFAULT_TARGET_TRIPLE_STRING "i686-unknown-linux"
+  #define DEFAULT_TARGET_TRIPLE_STRING DEFAULT_X86_TRIPLE_STRING
 #elif defined(DEFAULT_X86_64_CODEGEN)
-  #define DEFAULT_TARGET_TRIPLE_STRING "x86_64-unknown-linux"
+  #define DEFAULT_TARGET_TRIPLE_STRING DEFAULT_X86_64_TRIPLE_STRING
 #endif
 
 #if (defined(__VFP_FP__) && !defined(__SOFTFP__))
diff --git a/lib/ExecutionEngine/Android.mk b/lib/ExecutionEngine/Android.mk
index 02088cb..d101107 100644
--- a/lib/ExecutionEngine/Android.mk
+++ b/lib/ExecutionEngine/Android.mk
@@ -27,10 +27,12 @@
   BCCContextImpl.cpp \
   BCCRuntimeSymbolResolver.cpp \
   Compiler.cpp \
+  CompilerConfig.cpp \
   ELFObjectLoaderImpl.cpp \
   FileBase.cpp \
   GDBJIT.cpp \
   GDBJITRegistrar.cpp \
+  Initialization.cpp \
   InputFile.cpp \
   MCCacheWriter.cpp \
   MCCacheReader.cpp \
@@ -49,7 +51,8 @@
   Sha1Helper.cpp \
   Source.cpp \
   SymbolResolverProxy.cpp \
-  SymbolResolvers.cpp
+  SymbolResolvers.cpp \
+  TargetCompilerConfigs.cpp
 
 
 #=====================================================================
diff --git a/lib/ExecutionEngine/CompilerConfig.cpp b/lib/ExecutionEngine/CompilerConfig.cpp
new file mode 100644
index 0000000..faaaa97
--- /dev/null
+++ b/lib/ExecutionEngine/CompilerConfig.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CompilerConfig.h"
+
+#include <llvm/CodeGen/SchedulerRegistry.h>
+#include <llvm/MC/SubtargetFeature.h>
+#include <llvm/Support/TargetRegistry.h>
+
+#include "DebugHelper.h"
+#include "TargetCompilerConfigs.h"
+
+using namespace bcc;
+
+CompilerConfig::CompilerConfig(const std::string &pTriple)
+  : mTriple(pTriple), mTarget(NULL) {
+  //===--------------------------------------------------------------------===//
+  // Default setting of register sheduler
+  //===--------------------------------------------------------------------===//
+  llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
+
+  //===--------------------------------------------------------------------===//
+  // Default setting of target options
+  //===--------------------------------------------------------------------===//
+  // Use hardfloat ABI by default.
+  //
+  // TODO(all): Need to detect the CPU capability and decide whether to use
+  // softfp. To use softfp, change the following 2 lines to
+  //
+  // options.FloatABIType = llvm::FloatABI::Soft;
+  // options.UseSoftFloat = true;
+  mTargetOpts.FloatABIType = llvm::FloatABI::Soft;
+  mTargetOpts.UseSoftFloat = false;
+
+  // Enable frame pointer elimination optimization by default.
+  mTargetOpts.NoFramePointerElim = false;
+
+  //===--------------------------------------------------------------------===//
+  // Default setting for code model
+  //===--------------------------------------------------------------------===//
+  mCodeModel = llvm::CodeModel::Small;
+
+  //===--------------------------------------------------------------------===//
+  // Default setting for relocation model
+  //===--------------------------------------------------------------------===//
+  mRelocModel = llvm::Reloc::Default;
+
+  //===--------------------------------------------------------------------===//
+  // Default setting for optimization level (-O2)
+  //===--------------------------------------------------------------------===//
+  mOptLevel = llvm::CodeGenOpt::Default;
+
+  //===--------------------------------------------------------------------===//
+  // Default setting for architecture type
+  //===--------------------------------------------------------------------===//
+  mArchType = llvm::Triple::UnknownArch;
+
+  initializeTarget();
+  initializeArch();
+
+  return;
+}
+
+bool CompilerConfig::initializeTarget() {
+  std::string error;
+  mTarget = llvm::TargetRegistry::lookupTarget(mTriple, error);
+  if (mTarget != NULL) {
+    return true;
+  } else {
+    ALOGE("Cannot initialize llvm::Target for given triple '%s'! (%s)",
+          mTriple.c_str(), error.c_str());
+    return false;
+  }
+}
+
+void CompilerConfig::initializeArch() {
+  if (mTarget != NULL) {
+    mArchType = llvm::Triple::getArchTypeForLLVMName(mTarget->getName());
+  } else {
+    mArchType = llvm::Triple::UnknownArch;
+  }
+  return;
+}
+
+void CompilerConfig::setFeatureString(const std::vector<std::string> &pAttrs) {
+  llvm::SubtargetFeatures f;
+
+  for (std::vector<std::string>::const_iterator attr_iter = pAttrs.begin(),
+           attr_end = pAttrs.end();
+       attr_iter != attr_end; attr_iter++) {
+    f.AddFeature(*attr_iter);
+  }
+
+  mFeatureString = f.getString();
+  return;
+}
diff --git a/lib/ExecutionEngine/CompilerConfig.h b/lib/ExecutionEngine/CompilerConfig.h
new file mode 100644
index 0000000..d83086a
--- /dev/null
+++ b/lib/ExecutionEngine/CompilerConfig.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_EXECUTION_ENGINE_COMPILER_CONFIG_H
+#define BCC_EXECUTION_ENGINE_COMPILER_CONFIG_H
+
+#include <string>
+#include <vector>
+
+#include <llvm/ADT/Triple.h>
+#include <llvm/Support/CodeGen.h>
+#include <llvm/Target/TargetOptions.h>
+
+namespace llvm {
+
+class Target;
+
+} // end namespace llvm
+
+namespace bcc {
+
+class CompilerConfig {
+private:
+  //===--------------------------------------------------------------------===//
+  // Available Configurations
+  //===--------------------------------------------------------------------===//
+  std::string mTriple;
+
+  // Optional. If given, the name of the target CPU to generate code for.
+  std::string mCPU;
+
+  llvm::TargetOptions mTargetOpts;
+
+  llvm::CodeModel::Model mCodeModel;
+
+  llvm::CodeGenOpt::Level mOptLevel;
+
+  llvm::Reloc::Model mRelocModel;
+
+  // The list of target specific features to enable or disable -- this should
+  // be a list of strings starting with '+' (enable) or '-' (disable).
+  std::string mFeatureString;
+
+private:
+  //===--------------------------------------------------------------------===//
+  // These are generated by CompilerConfig during initialize().
+  //===--------------------------------------------------------------------===//
+  const llvm::Target *mTarget;
+  bool initializeTarget();
+
+  llvm::Triple::ArchType mArchType;
+  void initializeArch();
+
+public:
+  //===--------------------------------------------------------------------===//
+  // Getters
+  //===--------------------------------------------------------------------===//
+  inline const std::string &getTriple() const
+  { return mTriple; }
+
+  inline const std::string &getCPU() const
+  { return mCPU; }
+  inline void setCPU(const std::string &pCPU)
+  { mCPU = pCPU; }
+
+  inline const llvm::TargetOptions &getTargetOptions() const
+  { return mTargetOpts; }
+  inline llvm::TargetOptions &getTargetOptions()
+  { return mTargetOpts; }
+
+  inline llvm::CodeModel::Model getCodeModel() const
+  { return mCodeModel; }
+  inline void setCodeModel(llvm::CodeModel::Model pCodeMode)
+  { mCodeModel = pCodeMode; }
+
+  inline llvm::CodeGenOpt::Level getOptimizationLevel() const
+  { return mOptLevel; }
+  inline void setOptimizationLevel(llvm::CodeGenOpt::Level pOptLvl)
+  { mOptLevel = pOptLvl; }
+
+  inline llvm::Reloc::Model getRelocationModel() const
+  { return mRelocModel; }
+  inline void setRelocationModel(llvm::Reloc::Model pRelocModel)
+  { mRelocModel = pRelocModel; }
+
+  inline const llvm::Target *getTarget() const
+  { return mTarget; }
+
+  inline llvm::Triple::ArchType getArchType() const
+  { return mArchType; }
+
+  inline const std::string &getFeatureString() const
+  { return mFeatureString; }
+  void setFeatureString(const std::vector<std::string> &pAttrs);
+
+public:
+  CompilerConfig(const std::string &pTriple);
+
+  virtual ~CompilerConfig() { }
+};
+
+} // end namespace bcc
+
+#endif  // BCC_EXECUTION_ENGINE_COMPILER_CONFIG_H
diff --git a/lib/ExecutionEngine/Initialization.cpp b/lib/ExecutionEngine/Initialization.cpp
new file mode 100644
index 0000000..7cdb938
--- /dev/null
+++ b/lib/ExecutionEngine/Initialization.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Initialization.h"
+
+#include <cstdlib>
+
+#include <llvm/Support/ErrorHandling.h>
+#include <llvm/Support/TargetSelect.h>
+
+#include "Config.h"
+#include "DebugHelper.h"
+
+namespace {
+
+void llvm_error_handler(void *pUserData, const std::string &pMessage) {
+  ALOGE("%s", pMessage.c_str());
+  ::exit(1);
+}
+
+} // end anonymous namespace
+
+void bcc::init::Initialize() {
+  static bool is_initialized = false;
+
+  if (is_initialized) {
+    return;
+  }
+
+  // Setup error handler for LLVM.
+  llvm::remove_fatal_error_handler();
+  llvm::install_fatal_error_handler(llvm_error_handler, NULL);
+
+#if defined(PROVIDE_ARM_CODEGEN)
+  LLVMInitializeARMAsmPrinter();
+  LLVMInitializeARMTargetMC();
+  LLVMInitializeARMTargetInfo();
+  LLVMInitializeARMTarget();
+#endif
+
+#if defined(PROVIDE_MIPS_CODEGEN)
+  LLVMInitializeMipsAsmPrinter();
+  LLVMInitializeMipsTargetMC();
+  LLVMInitializeMipsTargetInfo();
+  LLVMInitializeMipsTarget();
+#endif
+
+#if defined(PROVIDE_X86_CODEGEN)
+  LLVMInitializeX86AsmPrinter();
+  LLVMInitializeX86TargetMC();
+  LLVMInitializeX86TargetInfo();
+  LLVMInitializeX86Target();
+#endif
+
+#if USE_DISASSEMBLER
+  InitializeDisassembler();
+#endif
+
+  is_initialized = true;
+
+  return;
+}
diff --git a/lib/ExecutionEngine/Initialization.h b/lib/ExecutionEngine/Initialization.h
new file mode 100644
index 0000000..9a357bc
--- /dev/null
+++ b/lib/ExecutionEngine/Initialization.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_EXECUTION_ENGINE_INITIALIZATION_H
+#define BCC_EXECUTION_ENGINE_INITIALIZATION_H
+
+namespace bcc {
+
+namespace init {
+
+void Initialize();
+
+} // end namespace init
+
+} // end namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_INITIALIZATION_H
diff --git a/lib/ExecutionEngine/TargetCompilerConfigs.cpp b/lib/ExecutionEngine/TargetCompilerConfigs.cpp
new file mode 100644
index 0000000..2e2f5da
--- /dev/null
+++ b/lib/ExecutionEngine/TargetCompilerConfigs.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TargetCompilerConfigs.h"
+
+using namespace bcc;
+
+//===----------------------------------------------------------------------===//
+// ARM
+//===----------------------------------------------------------------------===//
+#if defined(PROVIDE_ARM_CODEGEN)
+
+void ARMCompilerConfig::GetFeatureVector(std::vector<std::string> &pAttributes,
+                                         bool pEnableNEON) {
+#if defined(ARCH_ARM_HAVE_VFP)
+  pAttributes.push_back("+vfp3");
+#  if !defined(ARCH_ARM_HAVE_VFP_D32)
+  pAttributes.push_back("+d16");
+#  endif
+#endif
+
+#if defined(ARCH_ARM_HAVE_NEON) && !defined(DISABLE_ARCH_ARM_HAVE_NEON)
+  if (pEnableNEON) {
+    // FIXME(all): Turn NEON back on after debugging the rebase.
+    //attributes.push_back("+neon");
+    //attributes.push_back("+neonfp");
+    pAttributes.push_back("-neon");
+    pAttributes.push_back("-neonfp");
+  } else {
+    pAttributes.push_back("-neon");
+    pAttributes.push_back("-neonfp");
+  }
+#else
+  pAttributes.push_back("-neon");
+  pAttributes.push_back("-neonfp");
+#endif
+
+  return;
+}
+
+ARMCompilerConfig::ARMCompilerConfig()
+  : CompilerConfig(DEFAULT_ARM_TRIPLE_STRING) {
+
+  // Enable NEON by default.
+  mEnableNEON = true;
+
+  std::vector<std::string> attributes;
+  GetFeatureVector(attributes, /* pEnableNEON */mEnableNEON);
+  setFeatureString(attributes);
+
+  return;
+}
+
+bool ARMCompilerConfig::enableNEON(bool pEnable) {
+#if defined(ARCH_ARM_HAVE_NEON) && !defined(DISABLE_ARCH_ARM_HAVE_NEON)
+  if (mEnableNEON != pEnable) {
+    std::vector<std::string> attributes;
+    GetFeatureVector(attributes, pEnable);
+    setFeatureString(attributes);
+    mEnableNEON = pEnable;
+    return true;
+  }
+  // Fall-through
+#endif
+  return false;
+}
+#endif // defined(PROVIDE_ARM_CODEGEN)
diff --git a/lib/ExecutionEngine/TargetCompilerConfigs.h b/lib/ExecutionEngine/TargetCompilerConfigs.h
new file mode 100644
index 0000000..bf10a7a
--- /dev/null
+++ b/lib/ExecutionEngine/TargetCompilerConfigs.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_EXECUTION_ENGINE_TARGET_COMPILER_CONFIGS_H
+#define BCC_EXECUTION_ENGINE_TARGET_COMPILER_CONFIGS_H
+
+#include "CompilerConfig.h"
+#include "Config.h"
+
+namespace bcc {
+
+//===----------------------------------------------------------------------===//
+// ARM
+//===----------------------------------------------------------------------===//
+#if defined(PROVIDE_ARM_CODEGEN)
+class ARMCompilerConfig : public CompilerConfig {
+private:
+  bool mEnableNEON;
+
+  static void GetFeatureVector(std::vector<std::string> &pAttributes,
+                               bool pEnableNEON);
+
+public:
+  ARMCompilerConfig();
+
+  // Return true if config has been changed after returning from this function.
+  bool enableNEON(bool pEnable = true);
+};
+#endif // defined(PROVIDE_ARM_CODEGEN)
+
+//===----------------------------------------------------------------------===//
+// MIPS
+//===----------------------------------------------------------------------===//
+#if defined(PROVIDE_MIPS_CODEGEN)
+class MipsCompilerConfig : public CompilerConfig {
+public:
+  MipsCompilerConfig() : CompilerConfig(DEFAULT_MIPS_TRIPLE_STRING) {}
+};
+#endif // defined(PROVIDE_MIPS_CODEGEN)
+
+//===----------------------------------------------------------------------===//
+// X86 and X86_64
+//===----------------------------------------------------------------------===//
+#if defined(PROVIDE_X86_CODEGEN)
+class X86FamilyCompilerConfigBase : public CompilerConfig {
+protected:
+  X86FamilyCompilerConfigBase(const std::string &pTriple)
+    : CompilerConfig(pTriple) {
+    // Disable frame pointer elimination optimization on x86 family.
+    getTargetOptions().NoFramePointerElim = true;
+    return;
+  }
+};
+
+class X86_32CompilerConfig : public X86FamilyCompilerConfigBase {
+public:
+  X86_32CompilerConfig() :
+      X86FamilyCompilerConfigBase(DEFAULT_X86_TRIPLE_STRING) { }
+};
+
+class X86_64CompilerConfig : public X86FamilyCompilerConfigBase {
+public:
+  X86_64CompilerConfig() :
+      X86FamilyCompilerConfigBase(DEFAULT_X86_64_TRIPLE_STRING) {
+    setCodeModel(llvm::CodeModel::Medium);
+  }
+};
+#endif // defined(PROVIDE_X86_CODEGEN)
+
+//===----------------------------------------------------------------------===//
+// Default target
+//===----------------------------------------------------------------------===//
+class DefaultCompilerConfig : public
+#if defined(DEFAULT_ARM_CODEGEN)
+  ARMCompilerConfig
+#elif defined(DEFAULT_MIPS_CODEGEN)
+  MipsCompilerConfig
+#elif defined(DEFAULT_X86_CODEGEN)
+  X86_32CompilerConfig
+#elif defined(DEFAULT_X86_64_CODEGEN)
+  X86_64CompilerConfig
+#else
+#  error "Unsupported Default Target!"
+#endif
+{ };
+
+} // end namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_TARGET_COMPILER_CONFIGS_H