Introduce CompilerOption for compile() interface.

This provides flexibility. We can now setup different configuration
from the outside of compile() easily.

Change-Id: Ic4e593dd3c9f41de2fdfa492fecabd9f0e231463
diff --git a/lib/ExecutionEngine/Compiler.cpp b/lib/ExecutionEngine/Compiler.cpp
index be66edb..a299806 100644
--- a/lib/ExecutionEngine/Compiler.cpp
+++ b/lib/ExecutionEngine/Compiler.cpp
@@ -31,6 +31,7 @@
 #include "Runtime.h"
 #include "ScriptCompiled.h"
 #include "Sha1Helper.h"
+#include "CompilerOption.h"
 
 #if USE_MCJIT
 #include "librsloader.h"
@@ -56,7 +57,6 @@
 
 #include "llvm/Target/TargetData.h"
 #include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetOptions.h"
 
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FormattedStream.h"
@@ -312,7 +312,7 @@
 }
 
 
-int Compiler::compile(bool compileOnly) {
+int Compiler::compile(CompilerOption &option) {
   llvm::Target const *Target = NULL;
   llvm::TargetData *TD = NULL;
   llvm::TargetMachine *TM = NULL;
@@ -324,11 +324,6 @@
   llvm::NamedMDNode const *ExportFuncMetadata;
   llvm::NamedMDNode const *ObjectSlotMetadata;
 
-  llvm::TargetOptions Options;
-
-  llvm::CodeModel::Model CM;
-  llvm::Reloc::Model RM;
-
   if (mModule == NULL)  // No module was loaded
     return 0;
 
@@ -337,32 +332,6 @@
   if (hasError())
     goto on_bcc_compile_error;
 
-  // Determine code_model_is_medium
-#if defined(__HOST__)
-  bool code_model_is_medium;
-  bool no_frame_pointer_elimination;
-
-  {
-    // open a new scope otherwise compiler complains constructor of the folloinwg two being bypassed by previous 'goto' statement
-    const char *target_llvm_name = Target->getName();
-    const llvm::Triple::ArchType target_archtype = llvm::Triple::getArchTypeForLLVMName(target_llvm_name);
-    // Data address in X86_64 architecture may reside in a far-away place
-    code_model_is_medium = target_archtype == llvm::Triple::x86_64;
-    // Disable frame pointer elimination optimization for X86_64 and X86
-    no_frame_pointer_elimination = (target_archtype == llvm::Triple::x86_64 ||
-                                    target_archtype == llvm::Triple::x86);
-  }
-#elif defined(DEFAULT_X86_64_CODEGEN)
-  #define code_model_is_medium           true
-  #define no_frame_pointer_elimination   true
-#elif defined(DEFAULT_X86_CODEGEN)
-  #define code_model_is_medium           false
-  #define no_frame_pointer_elimination   true
-#else
-  #define code_model_is_medium           false
-  #define no_frame_pointer_elimination   false
-#endif
-
   if (!CPU.empty() || !Features.empty()) {
     llvm::SubtargetFeatures F;
 
@@ -374,27 +343,46 @@
     FeaturesStr = F.getString();
   }
 
-  // Setup LLVM Target Machine Options
-  Options.NoFramePointerElim = no_frame_pointer_elimination;
+  // Determine if code_model_is_medium
+  // And determine if no_frame_pointer_elimination
+#if defined(__HOST__)
+  bool code_model_is_medium;
+  bool no_frame_pointer_elimination;
 
-  // Use hardfloat ABI
-  //
-  // TODO(all): Need to detect the CPU capability and decide whether to use
-  // softfp. To use softfp, change following 2 lines to
-  //
-  // options.FloatABIType = llvm::FloatABI::Soft;
-  // options.UseSoftFloat = true;
-  Options.FloatABIType = llvm::FloatABI::Soft;
-  Options.UseSoftFloat = false;
+  {
+    // open a new scope otherwise compiler complains constructor of the
+    // folloinwg two being bypassed by previous 'goto' statement
+    const char *target_llvm_name = Target->getName();
+    const llvm::Triple::ArchType target_archtype = llvm::Triple::getArchTypeForLLVMName(target_llvm_name);
+    // Data address in X86_64 architecture may reside in a far-away place
+    code_model_is_medium = target_archtype == llvm::Triple::x86_64;
+    // Disable frame pointer elimination optimization for X86_64 and X86
+    no_frame_pointer_elimination = (target_archtype == llvm::Triple::x86_64 ||
+                                    target_archtype == llvm::Triple::x86);
+  }
+#elif defined(DEFAULT_X86_64_CODEGEN)
+# define code_model_is_medium           true
+# define no_frame_pointer_elimination   true
+#elif defined(DEFAULT_X86_CODEGEN)
+# define code_model_is_medium           false
+# define no_frame_pointer_elimination   true
+#else
+# define code_model_is_medium           false
+# define no_frame_pointer_elimination   false
+#endif
+
+  // Setup LLVM Target Machine Options
+  option.TargetOpt.NoFramePointerElim = no_frame_pointer_elimination;
 
   // This is set for the linker (specify how large of the virtual addresses
   // we can access for all unknown symbols.)
-  CM = code_model_is_medium? llvm::CodeModel::Medium : llvm::CodeModel::Small;
-
-  RM = llvm::Reloc::Static;
+  option.CodeModelOpt = code_model_is_medium ? llvm::CodeModel::Medium : llvm::CodeModel::Small;
 
   // Create LLVM Target Machine
-  TM = Target->createTargetMachine(Triple, CPU, FeaturesStr, Options, RM, CM);
+  TM = Target->createTargetMachine(Triple, CPU, FeaturesStr,
+                                   option.TargetOpt,
+                                   option.RelocModelOpt,
+                                   option.CodeModelOpt);
 
   if (TM == NULL) {
     setError("Failed to create target machine implementation for the"
@@ -431,7 +419,7 @@
     goto on_bcc_compile_error;
   }
 
-  if (compileOnly)
+  if (!option.LoadAfterCompile)
     return 0;
 
   // Load the ELF Object
diff --git a/lib/ExecutionEngine/Compiler.h b/lib/ExecutionEngine/Compiler.h
index 20dcd9e..2d4faf7 100644
--- a/lib/ExecutionEngine/Compiler.h
+++ b/lib/ExecutionEngine/Compiler.h
@@ -50,6 +50,7 @@
 
 namespace bcc {
   class ScriptCompiled;
+  struct CompilerOption;
 
   class Compiler {
   private:
@@ -151,7 +152,7 @@
 
     int linkModule(llvm::Module *module);
 
-    int compile(bool compileOnly);
+    int compile(CompilerOption &option);
 
     char const *getErrorMessage() {
       return mError.c_str();
diff --git a/lib/ExecutionEngine/CompilerOption.h b/lib/ExecutionEngine/CompilerOption.h
new file mode 100644
index 0000000..92754f0
--- /dev/null
+++ b/lib/ExecutionEngine/CompilerOption.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2010, 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_COMPILER_OPTION_H
+#define BCC_COMPILER_OPTION_H
+
+#include "Config.h"
+
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Support/CodeGen.h"
+
+namespace bcc {
+
+typedef struct CompilerOption {
+  llvm::TargetOptions TargetOpt;
+  llvm::CodeModel::Model CodeModelOpt;
+  llvm::Reloc::Model RelocModelOpt;
+  bool LoadAfterCompile;
+
+  // Constructor setup "default configuration". The "default configuration"
+  // here means the configuration for running RenderScript (more specifically,
+  // one can declare a CompilerOption object (call default constructor) and then
+  // pass to the Compiler::compiler() without any modification for RenderScript,
+  // see Script::prepareExecutable(...))
+  CompilerOption() {
+    //-- Setup options to llvm::TargetMachine --//
+
+    // Use hardfloat ABI
+    //
+    // TODO(all): Need to detect the CPU capability and decide whether to use
+    // softfp. To use softfp, change following 2 lines to
+    //
+    // options.FloatABIType = llvm::FloatABI::Soft;
+    // options.UseSoftFloat = true;
+    TargetOpt.FloatABIType = llvm::FloatABI::Soft;
+    TargetOpt.UseSoftFloat = false;
+
+    //-- Setup relocation model  --//
+    RelocModelOpt = llvm::Reloc::Static;
+
+    //-- Load the result object after successful compilation  --//
+    LoadAfterCompile = true;
+  }
+} CompilerOption;
+
+} // namespace bcc
+
+#endif  // BCC_COMPILER_OPTION_H
diff --git a/lib/ExecutionEngine/Script.cpp b/lib/ExecutionEngine/Script.cpp
index 854e5a1..aae0692 100644
--- a/lib/ExecutionEngine/Script.cpp
+++ b/lib/ExecutionEngine/Script.cpp
@@ -25,6 +25,7 @@
 
 #include "MCCacheReader.h"
 #include "MCCacheWriter.h"
+#include "CompilerOption.h"
 
 #if USE_OLD_JIT
 #include "OldJIT/ContextManager.h"
@@ -198,7 +199,10 @@
     }
   }
 #endif
-  int status = internalCompile(true);
+
+  CompilerOption option;
+  option.LoadAfterCompile = false;
+  int status = internalCompile(option);
   if (status != 0) {
     ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
   }
@@ -232,7 +236,8 @@
   }
 #endif
 
-  int status = internalCompile(false);
+  CompilerOption option;
+  int status = internalCompile(option);
   if (status != 0) {
     ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
   }
@@ -321,7 +326,7 @@
 }
 #endif
 
-int Script::internalCompile(bool compileOnly) {
+int Script::internalCompile(CompilerOption &option) {
   // Create the ScriptCompiled object
   mCompiled = new (std::nothrow) ScriptCompiled(this);
 
@@ -367,7 +372,7 @@
   }
 
   // Compile and JIT the code
-  if (mCompiled->compile(compileOnly) != 0) {
+  if (mCompiled->compile(option) != 0) {
     ALOGE("Unable to compile.\n");
     return 1;
   }
diff --git a/lib/ExecutionEngine/Script.h b/lib/ExecutionEngine/Script.h
index 2855240..83cc948 100644
--- a/lib/ExecutionEngine/Script.h
+++ b/lib/ExecutionEngine/Script.h
@@ -35,6 +35,7 @@
   class ScriptCompiled;
   class ScriptCached;
   class SourceInfo;
+  struct CompilerOption;
 
   namespace ScriptStatus {
     enum StatusType {
@@ -179,7 +180,7 @@
 #if USE_CACHE
     int internalLoadCache(bool checkOnly);
 #endif
-    int internalCompile(bool compileOnly);
+    int internalCompile(CompilerOption&);
 
   };
 
diff --git a/lib/ExecutionEngine/ScriptCompiled.h b/lib/ExecutionEngine/ScriptCompiled.h
index 6a1a9e8..e4acc16 100644
--- a/lib/ExecutionEngine/ScriptCompiled.h
+++ b/lib/ExecutionEngine/ScriptCompiled.h
@@ -33,6 +33,8 @@
 }
 
 namespace bcc {
+  struct CompilerOption;
+
   class ScriptCompiled {
     friend class Compiler;
     friend class CodeEmitter;
@@ -87,8 +89,8 @@
       return mCompiler.linkModule(module);
     }
 
-    int compile(bool compileOnly) {
-      return mCompiler.compile(compileOnly);
+    int compile(CompilerOption &option) {
+      return mCompiler.compile(option);
     }
 
     char const *getCompilerErrorMessage() {