Fix the LLVM build. Separate out libart-compiler-llvm.so.

After this refactoring:
If (!USE_LLVM_COMPILER), I pass the test-art and boot the phone alright.
The behavior is the same for non-LLVM builds as before. Multi-target
art-compiler shared libraries are generated as before.
If (USE_LLVM_COMPILER), I generate libart-compiler-llvm.so successfully.

Note that the ideal refactoring for the next step will be to always build
art-compiler and LLVM-[arm|mips|x86] shared libraries. Currently, we
haven't removed all the ifdefs for libart.so yet, so this is not ideal yet.
Reason for not-done-yet is that the next step requires discussions.
I can remove all the ifdefs today, but then the (!USE_LLVM_COMPILER)
build will incur extra fields and overhead.

This refactoring allows us to restore the LLVM build situation to be before
the breakage yesterday, so we can continue making forward progress again.

One difficulty in the refactoring is that LLVM is not a method compiler
in default, unlike (!USE_LLVM_COMPILER). LLVM actually compiles an LLVM module
at a time normally. So we need to do more call backs and tell
libart-compiler-llvm.so in each invocation where we are in terms of
OatCompilationUnit.

Another difficulty is that currently our LLVM compiler is not
multithreaded and requires locking, unlike (!USE_LLVM_COMPILER). So more
callbacks are needed. This will be fixed when we fix the multithreading
issue.

Change-Id: I93bce21b6d673254188f2a60b1a7f91b508e497f
diff --git a/Android.mk b/Android.mk
index 8ecd0f3..904a5f1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -28,6 +28,9 @@
 
 include $(build_path)/Android.libart.mk
 include $(build_path)/Android.libart-compiler.mk
+ifeq ($(ART_USE_LLVM_COMPILER),true)
+include $(build_path)/Android.libart-compiler-llvm.mk
+endif
 include $(build_path)/Android.executable.mk
 
 # *_DEPENDENCIES depend on Android.executable.mk and are needed by Android.gtest.mk
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 7d9ef81..df4c5a9 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -56,10 +56,6 @@
 	-fno-align-jumps \
 	-fstrict-aliasing
 
-ifeq ($(ART_USE_LLVM_COMPILER),true)
-art_cflags += -DART_USE_LLVM_COMPILER=1
-endif
-
 ifeq ($(HOST_OS),linux)
   art_non_debug_cflags := \
 	-Wframe-larger-than=1728
@@ -206,17 +202,8 @@
 
 ifeq ($(ART_USE_LLVM_COMPILER),true)
 LIBART_COMMON_SRC_FILES += \
-	src/compiler_llvm/compilation_unit.cc \
-	src/compiler_llvm/compiler_llvm.cc \
-	src/compiler_llvm/dalvik_reg.cc \
-	src/compiler_llvm/frontend.cc \
-	src/compiler_llvm/generated/art_module.cc \
 	src/compiler_llvm/inferred_reg_category_map.cc \
-	src/compiler_llvm/ir_builder.cc \
-	src/compiler_llvm/jni_compiler.cc \
-	src/compiler_llvm/method_compiler.cc \
 	src/compiler_llvm/runtime_support_llvm.cc \
-	src/compiler_llvm/upcall_compiler.cc \
 	src/compiler_llvm/utils_llvm.cc
 endif
 
diff --git a/build/Android.executable.mk b/build/Android.executable.mk
index cc71aac..5f139ee 100644
--- a/build/Android.executable.mk
+++ b/build/Android.executable.mk
@@ -17,6 +17,11 @@
 ART_HOST_EXECUTABLES :=
 ART_TARGET_EXECUTABLES :=
 
+ART_EXECUTABLES_CFLAGS :=
+ifeq ($(ART_USE_LLVM_COMPILER),true)
+  ART_EXECUTABLES_CFLAGS += -DART_USE_LLVM_COMPILER=1
+endif
+
 # $(1): executable ("d" will be appended for debug version)
 # $(2): source
 # $(3): target or host
@@ -55,15 +60,16 @@
     LOCAL_MODULE := $$(art_executable)d
   endif
 
+  LOCAL_CFLAGS := $(ART_EXECUTABLES_CFLAGS)
   ifeq ($$(art_target_or_host),target)
-    LOCAL_CFLAGS := $(ART_TARGET_CFLAGS)
+    LOCAL_CFLAGS += $(ART_TARGET_CFLAGS)
     ifeq ($$(art_ndebug_or_debug),debug)
       LOCAL_CFLAGS += $(ART_TARGET_DEBUG_CFLAGS)
     else
       LOCAL_CFLAGS += $(ART_TARGET_NON_DEBUG_CFLAGS)
     endif
   else # host
-    LOCAL_CFLAGS := $(ART_HOST_CFLAGS)
+    LOCAL_CFLAGS += $(ART_HOST_CFLAGS)
     ifeq ($$(art_ndebug_or_debug),debug)
       LOCAL_CFLAGS += $(ART_HOST_DEBUG_CFLAGS)
     else
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index c44a5e3..c85b170 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -19,6 +19,11 @@
 ART_HOST_TEST_TARGETS :=
 ART_TARGET_TEST_TARGETS :=
 
+ART_TEST_CFLAGS :=
+ifeq ($(ART_USE_LLVM_COMPILER),true)
+  ART_TEST_CFLAGS += -DART_USE_LLVM_COMPILER=1
+endif
+
 # $(1): target or host
 # $(2): file name
 define build-art-test
@@ -61,8 +66,9 @@
     LOCAL_LDFLAGS := -Wl,--export-dynamic -Wl,-u,Java_MyClass_bar -Wl,-u,Java_MyClass_sbar
   endif
 
+  LOCAL_CFLAGS := $(ART_TEST_CFLAGS)
   ifeq ($$(art_target_or_host),target)
-    LOCAL_CFLAGS := $(ART_TARGET_CFLAGS) $(ART_TARGET_DEBUG_CFLAGS)
+    LOCAL_CFLAGS += $(ART_TARGET_CFLAGS) $(ART_TARGET_DEBUG_CFLAGS)
     LOCAL_SHARED_LIBRARIES += libdl libicuuc libicui18n libnativehelper libstlport libz
     LOCAL_STATIC_LIBRARIES += libgtest libgtest_main
     LOCAL_MODULE_PATH := $(ART_NATIVETEST_OUT)
@@ -70,7 +76,7 @@
     art_gtest_exe := $$(LOCAL_MODULE_PATH)/$$(LOCAL_MODULE)
     ART_TARGET_TEST_EXECUTABLES += $$(art_gtest_exe)
   else # host
-    LOCAL_CFLAGS := $(ART_HOST_CFLAGS) $(ART_HOST_DEBUG_CFLAGS)
+    LOCAL_CFLAGS += $(ART_HOST_CFLAGS) $(ART_HOST_DEBUG_CFLAGS)
     LOCAL_SHARED_LIBRARIES += libicuuc-host libicui18n-host libnativehelper libz-host
     # glibc complains about double frees if you include both libraries, but Mac OS
     # complains about unresolved symbols if you don't!
diff --git a/build/Android.libart-compiler-llvm.mk b/build/Android.libart-compiler-llvm.mk
new file mode 100644
index 0000000..bb7b458
--- /dev/null
+++ b/build/Android.libart-compiler-llvm.mk
@@ -0,0 +1,198 @@
+#
+# Copyright (C) 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.
+#
+
+
+LIBART_COMPILER_LLVM_CFLAGS := -DART_USE_LLVM_COMPILER=1
+
+LIBART_COMPILER_LLVM_SRC_FILES += \
+	src/compiler_llvm/compilation_unit.cc \
+	src/compiler_llvm/compiler_llvm.cc \
+	src/compiler_llvm/dalvik_reg.cc \
+	src/compiler_llvm/frontend.cc \
+	src/compiler_llvm/generated/art_module.cc \
+	src/compiler_llvm/inferred_reg_category_map.cc \
+	src/compiler_llvm/ir_builder.cc \
+	src/compiler_llvm/jni_compiler.cc \
+	src/compiler_llvm/method_compiler.cc \
+	src/compiler_llvm/runtime_support_llvm.cc \
+	src/compiler_llvm/upcall_compiler.cc \
+	src/compiler_llvm/utils_llvm.cc
+
+# $(1): target or host
+# $(2): ndebug or debug
+# $(3): architecture name
+# $(4): list of source files
+define build-libart-compiler-llvm
+  ifneq ($(1),target)
+    ifneq ($(1),host)
+      $$(error expected target or host for argument 1, received $(1))
+    endif
+  endif
+  ifneq ($(2),ndebug)
+    ifneq ($(2),debug)
+      $$(error expected ndebug or debug for argument 2, received $(2))
+    endif
+  endif
+
+  art_target_or_host := $(1)
+  art_ndebug_or_debug := $(2)
+  libart_compiler_llvm_src_files := $(3)
+
+  include $(CLEAR_VARS)
+  ifeq ($$(art_target_or_host),target)
+    include external/stlport/libstlport.mk
+  endif
+  LOCAL_CPP_EXTENSION := $(ART_CPP_EXTENSION)
+  ifeq ($$(art_ndebug_or_debug),ndebug)
+    LOCAL_MODULE := libart-compiler-llvm
+  else # debug
+    LOCAL_MODULE := libartd-compiler-llvm
+  endif
+
+  LOCAL_MODULE_TAGS := optional
+  LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+
+  LOCAL_SRC_FILES := $(libart_compiler_llvm_src_files)
+  LOCAL_CFLAGS := $(LIBART_COMPILER_LLVM_CFLAGS)
+  ifeq ($$(art_target_or_host),target)
+    LOCAL_CFLAGS += $(ART_TARGET_CFLAGS)
+  else # host
+    LOCAL_CFLAGS += $(ART_HOST_CFLAGS)
+  endif
+
+  LOCAL_C_INCLUDES += $(ART_C_INCLUDES)
+  LOCAL_C_INCLUDES += frameworks/compile/linkloader
+  libart_compiler_llvm_arm_STATIC_LIBRARIES := \
+    libLLVMARMInfo \
+    libLLVMARMDisassembler \
+    libLLVMARMAsmParser \
+    libLLVMARMAsmPrinter \
+    libLLVMARMCodeGen \
+    libLLVMARMDesc
+
+  libart_compiler_llvm_mips_STATIC_LIBRARIES := \
+    libLLVMMipsInfo \
+    libLLVMMipsCodeGen \
+    libLLVMMipsDesc \
+    libLLVMMipsAsmPrinter \
+
+  libart_compiler_llvm_x86_STATIC_LIBRARIES := \
+    libLLVMX86Info \
+    libLLVMX86AsmParser \
+    libLLVMX86CodeGen \
+    libLLVMX86Disassembler \
+    libLLVMX86Desc \
+    libLLVMX86AsmPrinter \
+    libLLVMX86Utils
+
+  ifeq ($$(art_target_or_host),target)
+    LOCAL_STATIC_LIBRARIES += \
+      $$(libart_compiler_llvm_arm_STATIC_LIBRARIES)
+  else
+    LOCAL_STATIC_LIBRARIES += \
+      $$(libart_compiler_llvm_arm_STATIC_LIBRARIES) \
+      $$(libart_compiler_llvm_mips_STATIC_LIBRARIES) \
+      $$(libart_compiler_llvm_x86_STATIC_LIBRARIES)
+  endif
+
+  LOCAL_STATIC_LIBRARIES += \
+    libLLVMLinker \
+    libLLVMipo \
+    libLLVMBitWriter \
+    libLLVMBitReader \
+    libLLVMAsmPrinter \
+    libLLVMSelectionDAG \
+    libLLVMCodeGen \
+    libLLVMScalarOpts \
+    libLLVMInstCombine \
+    libLLVMInstrumentation \
+    libLLVMTransformUtils \
+    libLLVMipa \
+    libLLVMAnalysis \
+    libLLVMTarget \
+    libLLVMMC \
+    libLLVMMCParser \
+    libLLVMCore \
+    libLLVMSupport \
+    librsloader
+  LOCAL_SHARED_LIBRARIES := liblog libnativehelper
+  ifeq ($$(art_target_or_host),target)
+    LOCAL_SHARED_LIBRARIES += libcutils libstlport libz libdl
+    LOCAL_SHARED_LIBRARIES += libdynamic_annotations # tsan support
+    LOCAL_SHARED_LIBRARIES += libcorkscrew # native stack trace support
+  else # host
+    LOCAL_STATIC_LIBRARIES += libcutils
+    LOCAL_SHARED_LIBRARIES += libz-host
+    LOCAL_SHARED_LIBRARIES += libdynamic_annotations-host # tsan support
+    LOCAL_LDLIBS := -ldl -lpthread
+    ifeq ($(HOST_OS),linux)
+      LOCAL_LDLIBS += -lrt
+    endif
+  endif
+  ifeq ($$(art_ndebug_or_debug),debug)
+    ifeq ($$(art_target_or_host),target)
+      LOCAL_CFLAGS += $(ART_TARGET_DEBUG_CFLAGS)
+    else # host
+      LOCAL_CFLAGS += $(ART_HOST_DEBUG_CFLAGS)
+    endif
+    LOCAL_SHARED_LIBRARIES += libartd
+  else
+    ifeq ($$(art_target_or_host),target)
+      LOCAL_CFLAGS += $(ART_TARGET_NON_DEBUG_CFLAGS)
+    else # host
+      LOCAL_CFLAGS += $(ART_HOST_NON_DEBUG_CFLAGS)
+    endif
+    LOCAL_SHARED_LIBRARIES += libart
+  endif
+  ifeq ($$(art_target_or_host),target)
+    include $(LLVM_GEN_INTRINSICS_MK)
+    include $(LLVM_DEVICE_BUILD_MK)
+    include $(BUILD_SHARED_LIBRARY)
+  else # host
+    LOCAL_IS_HOST_MODULE := true
+    include $(LLVM_GEN_INTRINSICS_MK)
+    include $(LLVM_HOST_BUILD_MK)
+    include $(BUILD_HOST_SHARED_LIBRARY)
+  endif
+
+  ifeq ($$(art_target_or_host),target)
+    ifeq ($$(art_ndebug_or_debug),debug)
+      $(TARGET_OUT_EXECUTABLES)/dex2oatd: $$(LOCAL_INSTALLED_MODULE)
+    else
+      $(TARGET_OUT_EXECUTABLES)/dex2oat: $$(LOCAL_INSTALLED_MODULE)
+    endif
+  else # host
+    ifeq ($$(art_ndebug_or_debug),debug)
+      $(HOST_OUT_EXECUTABLES)/dex2oatd: $$(LOCAL_INSTALLED_MODULE)
+    else
+      $(HOST_OUT_EXECUTABLES)/dex2oat: $$(LOCAL_INSTALLED_MODULE)
+    endif
+  endif
+
+endef
+
+ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
+  $(eval $(call build-libart-compiler-llvm,target,ndebug,$(LIBART_COMPILER_LLVM_SRC_FILES)))
+endif
+ifeq ($(ART_BUILD_TARGET_DEBUG),true)
+  $(eval $(call build-libart-compiler-llvm,target,debug,$(LIBART_COMPILER_LLVM_SRC_FILES)))
+endif
+ifeq ($(ART_BUILD_HOST_NDEBUG),true)
+  $(eval $(call build-libart-compiler-llvm,host,ndebug,$(LIBART_COMPILER_LLVM_SRC_FILES)))
+endif
+ifeq ($(ART_BUILD_HOST_DEBUG),true)
+  $(eval $(call build-libart-compiler-llvm,host,debug,$(LIBART_COMPILER_LLVM_SRC_FILES)))
+endif
diff --git a/build/Android.libart.mk b/build/Android.libart.mk
index db05eac..5bc8f46 100644
--- a/build/Android.libart.mk
+++ b/build/Android.libart.mk
@@ -14,6 +14,11 @@
 # limitations under the License.
 #
 
+LIBART_CFLAGS :=
+ifeq ($(ART_USE_LLVM_COMPILER),true)
+  LIBART_CFLAGS += -DART_USE_LLVM_COMPILER=1
+endif
+
 # $(1): target or host
 # $(2): ndebug or debug
 define build-libart
@@ -50,10 +55,12 @@
   else # host
     LOCAL_SRC_FILES := $(LIBART_HOST_SRC_FILES)
   endif
+
+  LOCAL_CFLAGS := $(LIBART_CFLAGS)
   ifeq ($$(art_target_or_host),target)
-    LOCAL_CFLAGS := $(ART_TARGET_CFLAGS)
+    LOCAL_CFLAGS += $(ART_TARGET_CFLAGS)
   else # host
-    LOCAL_CFLAGS := $(ART_HOST_CFLAGS)
+    LOCAL_CFLAGS += $(ART_HOST_CFLAGS)
   endif
   ifeq ($$(art_ndebug_or_debug),debug)
     ifeq ($$(art_target_or_host),target)
@@ -72,6 +79,7 @@
   LOCAL_C_INCLUDES += $(ART_C_INCLUDES)
   ifeq ($(ART_USE_LLVM_COMPILER),true)
     LOCAL_C_INCLUDES += frameworks/compile/linkloader
+    LOCAL_STATIC_LIBRARIES += librsloader
     libart_arm_STATIC_LIBRARIES := \
       libLLVMARMInfo \
       libLLVMARMDisassembler \
@@ -123,8 +131,7 @@
       libLLVMMC \
       libLLVMMCParser \
       libLLVMCore \
-      libLLVMSupport \
-      librsloader
+      libLLVMSupport
   endif
   LOCAL_SHARED_LIBRARIES := liblog libnativehelper
   ifeq ($$(art_target_or_host),target)
diff --git a/src/common_test.h b/src/common_test.h
index 7da5c77..29ed57c 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -352,7 +352,7 @@
     class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
     compiler_.reset(new Compiler(instruction_set, false, 2, false, NULL));
 #if defined(ART_USE_LLVM_COMPILER)
-    compiler_->GetCompilerLLVM()->SetElfFileName("gtest");
+    compiler_->SetElfFileName("gtest");
 #endif
 
     Runtime::Current()->GetHeap()->VerifyHeap();  // Check for heap corruption before the test
diff --git a/src/compiled_method.cc b/src/compiled_method.cc
index 259ee44..e122816 100644
--- a/src/compiled_method.cc
+++ b/src/compiled_method.cc
@@ -24,7 +24,7 @@
     : instruction_set_(instruction_set), func_(func), frame_size_in_bytes_(0),
       core_spill_mask_(0), fp_spill_mask_(0) {
 }
-#else
+#endif
 CompiledMethod::CompiledMethod(InstructionSet instruction_set,
                                const std::vector<uint8_t>& code,
                                const size_t frame_size_in_bytes,
@@ -68,7 +68,6 @@
 
   DCHECK_EQ(vmap_table_[0], static_cast<uint32_t>(__builtin_popcount(core_spill_mask) + __builtin_popcount(fp_spill_mask)));
 }
-#endif
 
 void CompiledMethod::SetGcMap(const std::vector<uint8_t>& gc_map) {
   CHECK_NE(gc_map.size(), 0U);
@@ -180,12 +179,11 @@
 CompiledInvokeStub::CompiledInvokeStub(llvm::Function* func) : func_(func) {
   CHECK_NE(func, static_cast<llvm::Function*>(NULL));
 }
-#else
+#endif
 CompiledInvokeStub::CompiledInvokeStub(std::vector<uint8_t>& code) {
   CHECK_NE(code.size(), 0U);
   code_ = code;
 }
-#endif
 
 CompiledInvokeStub::~CompiledInvokeStub() {}
 
diff --git a/src/compiled_method.h b/src/compiled_method.h
index 715b5d2..e6fdbaa 100644
--- a/src/compiled_method.h
+++ b/src/compiled_method.h
@@ -34,7 +34,7 @@
   // Create a CompiledMethod from the oatCompileMethod
   CompiledMethod(InstructionSet instruction_set,
                  llvm::Function* func);
-#else
+#endif
   // Create a CompiledMethod from the oatCompileMethod
   CompiledMethod(InstructionSet instruction_set,
                  const std::vector<uint8_t>& code,
@@ -43,7 +43,6 @@
                  const uint32_t fp_spill_mask,
                  const std::vector<uint32_t>& mapping_table,
                  const std::vector<uint16_t>& vmap_table);
-#endif
 
   // Add a GC map to a CompiledMethod created by oatCompileMethod
   void SetGcMap(const std::vector<uint8_t>& gc_map);
@@ -100,9 +99,8 @@
  public:
 #if defined(ART_USE_LLVM_COMPILER)
   explicit CompiledInvokeStub(llvm::Function* func);
-#else
-  explicit CompiledInvokeStub(std::vector<uint8_t>& code);
 #endif
+  explicit CompiledInvokeStub(std::vector<uint8_t>& code);
   ~CompiledInvokeStub();
   const std::vector<uint8_t>& GetCode() const;
  private:
diff --git a/src/compiler.cc b/src/compiler.cc
index 3f7f637..447d6f5 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -40,10 +40,6 @@
 #include <mach-o/dyld.h>
 #endif
 
-#if defined(ART_USE_LLVM_COMPILER)
-#include "compiler_llvm/compiler_llvm.h"
-#endif
-
 namespace art {
 
 namespace arm {
@@ -230,7 +226,11 @@
 #endif
 
   // Work out the filename for the compiler library.
+#if !defined(ART_USE_LLVM_COMPILER)
   std::string library_name(StringPrintf("art%s-compiler-%s", suffix, instruction_set_name.c_str()));
+#else
+  std::string library_name(StringPrintf("art%s-compiler-llvm", suffix));
+#endif
   std::string filename(StringPrintf(OS_SHARED_LIB_FORMAT_STR, library_name.c_str()));
 
 #if defined(__APPLE__)
@@ -282,16 +282,15 @@
       support_debugging_(support_debugging),
       stats_(new AOTCompilationStats),
       image_classes_(image_classes),
-#if !defined(ART_USE_LLVM_COMPILER)
+#if defined(ART_USE_LLVM_COMPILER)
+      compiler_llvm_(NULL),
+#endif
       compiler_library_(NULL),
       compiler_(NULL),
       jni_compiler_(NULL),
       create_invoke_stub_(NULL)
-#else
-      compiler_llvm_(new compiler_llvm::CompilerLLVM(this, instruction_set))
-#endif
 {
-  std::string compiler_so_name(MakeCompilerSoName(instruction_set));
+  std::string compiler_so_name(MakeCompilerSoName(instruction_set_));
   compiler_library_ = dlopen(compiler_so_name.c_str(), RTLD_LAZY);
   if (compiler_library_ == NULL) {
     LOG(FATAL) << "Couldn't find compiler library " << compiler_so_name << ": " << dlerror();
@@ -321,6 +320,12 @@
     MutexLock mu(compiled_invoke_stubs_lock_);
     STLDeleteValues(&compiled_invoke_stubs_);
   }
+#if defined(ART_USE_LLVM_COMPILER)
+  CompilerCallbackFn f = FindFunction<CompilerCallbackFn>(MakeCompilerSoName(instruction_set_),
+                                                          compiler_library_,
+                                                          "compilerLLVMDispose");
+  (*f)(*this);
+#endif
   if (compiler_library_ != NULL) {
     VLOG(compiler) << "dlclose(" << compiler_library_ << ")";
     dlclose(compiler_library_);
@@ -427,7 +432,10 @@
                            const std::vector<const DexFile*>& dex_files) {
   SetGcMaps(class_loader, dex_files);
 #if defined(ART_USE_LLVM_COMPILER)
-  compiler_llvm_->MaterializeRemainder();
+  CompilerCallbackFn f = FindFunction<CompilerCallbackFn>(MakeCompilerSoName(instruction_set_),
+                                                          compiler_library_,
+                                                          "compilerLLVMMaterializeRemainder");
+  (*f)(*this);
 #endif
 }
 
@@ -1057,13 +1065,16 @@
   const ClassLoader* class_loader = context->GetClassLoader();
   const DexFile& dex_file = *context->GetDexFile();
   const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
-
 #if defined(ART_USE_LLVM_COMPILER)
-  compiler_llvm::CompilerLLVM* compiler_llvm = context->GetCompiler()->GetCompilerLLVM();
-
-  MutexLock GUARD(compiler_llvm->compiler_lock_);
   // TODO: Remove this.  We should not lock the compiler_lock_ in CompileClass()
-  // However, without this mutex lock, we will get segmentation fault.
+  // However, without this mutex lock, we will get segmentation fault before
+  // LLVM becomes multithreaded.
+  Compiler* cmplr = context->GetCompiler();
+  CompilerMutexLockFn f =
+      FindFunction<CompilerMutexLockFn>(MakeCompilerSoName(cmplr->GetInstructionSet()),
+                                        cmplr->compiler_library_,
+                                        "compilerLLVMMutexLock");
+  UniquePtr<MutexLock> GUARD((*f)(*cmplr));
 #endif
 
   if (SkipClass(class_loader, dex_file, class_def)) {
@@ -1102,7 +1113,11 @@
   DCHECK(!it.HasNext());
 
 #if defined(ART_USE_LLVM_COMPILER)
-  compiler_llvm->MaterializeIfThresholdReached();
+  CompilerCallbackFn fn =
+      FindFunction<CompilerCallbackFn>(MakeCompilerSoName(cmplr->GetInstructionSet()),
+                                       cmplr->compiler_library_,
+                                       "compilerLLVMMaterializeIfThresholdReached");
+                                       (*fn)(*cmplr);
 #endif
 }
 
@@ -1117,30 +1132,13 @@
   CompiledMethod* compiled_method = NULL;
   uint64_t start_ns = NanoTime();
 
-#if defined(ART_USE_LLVM_COMPILER)
-  ClassLinker *class_linker = Runtime::Current()->GetClassLinker();
-  DexCache *dex_cache = class_linker->FindDexCache(dex_file);
-
-  OatCompilationUnit oat_compilation_unit(
-    class_loader, class_linker, dex_file, *dex_cache, code_item,
-    method_idx, access_flags);
-#endif
-
   if ((access_flags & kAccNative) != 0) {
-#if defined(ART_USE_LLVM_COMPILER)
-    compiled_method = compiler_llvm_->CompileNativeMethod(&oat_compilation_unit);
-#else
     compiled_method = (*jni_compiler_)(*this, access_flags, method_idx, class_loader, dex_file);
-#endif
     CHECK(compiled_method != NULL);
   } else if ((access_flags & kAccAbstract) != 0) {
   } else {
-#if defined(ART_USE_LLVM_COMPILER)
-    compiled_method = compiler_llvm_->CompileDexMethod(&oat_compilation_unit);
-#else
     compiled_method = (*compiler_)(*this, code_item, access_flags, method_idx, class_loader,
                                    dex_file);
-#endif
     CHECK(compiled_method != NULL) << PrettyMethod(method_idx, dex_file);
   }
   uint64_t duration_ns = NanoTime() - start_ns;
@@ -1163,7 +1161,7 @@
   const CompiledInvokeStub* compiled_invoke_stub = FindInvokeStub(is_static, shorty);
   if (compiled_invoke_stub == NULL) {
 #if defined(ART_USE_LLVM_COMPILER)
-    compiled_invoke_stub = compiler_llvm_->CreateInvokeStub(is_static, shorty);
+    compiled_invoke_stub = (*create_invoke_stub_)(*this, is_static, shorty, shorty_len);
 #else
     compiled_invoke_stub = (*create_invoke_stub_)(is_static, shorty, shorty_len);
 #endif
@@ -1287,11 +1285,17 @@
 
 #if defined(ART_USE_LLVM_COMPILER)
 void Compiler::SetElfFileName(std::string const& filename) {
-  compiler_llvm_->SetElfFileName(filename);
+  elf_filename_ = filename;
 }
 
 void Compiler::SetBitcodeFileName(std::string const& filename) {
-  compiler_llvm_->SetBitcodeFileName(filename);
+  bitcode_filename_ = filename;
+}
+std::string const& Compiler::GetElfFileName() {
+  return elf_filename_;
+}
+std::string const& Compiler::GetBitcodeFileName() {
+  return bitcode_filename_;
 }
 #endif
 
diff --git a/src/compiler.h b/src/compiler.h
index e53cc46..134e71b 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -30,12 +30,14 @@
 #include "object.h"
 #include "runtime.h"
 
-#if defined(ART_USE_LLVM_COMPILER)
-#include "compiler_llvm/compiler_llvm.h"
-#endif
-
 namespace art {
 
+#if defined(ART_USE_LLVM_COMPILER)
+namespace compiler_llvm {
+class CompilerLLVM;
+}
+#endif
+
 class AOTCompilationStats;
 class Context;
 class OatCompilationUnit;
@@ -125,9 +127,14 @@
 #if defined(ART_USE_LLVM_COMPILER)
   void SetElfFileName(std::string const& filename);
   void SetBitcodeFileName(std::string const& filename);
+  std::string const& GetElfFileName();
+  std::string const& GetBitcodeFileName();
 
+  void SetCompilerLLVM(compiler_llvm::CompilerLLVM* compiler_llvm) {
+    compiler_llvm_ = compiler_llvm;
+  }
   compiler_llvm::CompilerLLVM* GetCompilerLLVM() const {
-    return compiler_llvm_.get();
+    return compiler_llvm_;
   }
 #endif
 
@@ -195,8 +202,12 @@
   const std::set<std::string>* image_classes_;
 
 #if defined(ART_USE_LLVM_COMPILER)
-  UniquePtr<compiler_llvm::CompilerLLVM> compiler_llvm_;
-#else
+  compiler_llvm::CompilerLLVM* compiler_llvm_;
+  std::string elf_filename_;
+  std::string bitcode_filename_;
+  typedef void (*CompilerCallbackFn)(Compiler& compiler);
+  typedef MutexLock* (*CompilerMutexLockFn)(Compiler& compiler);
+#endif
   void* compiler_library_;
 
   typedef CompiledMethod* (*CompilerFn)(Compiler& compiler,
@@ -211,11 +222,14 @@
                                            const ClassLoader* class_loader,
                                            const DexFile& dex_file);
   JniCompilerFn jni_compiler_;
-
+#if !defined(ART_USE_LLVM_COMPILER)
   typedef CompiledInvokeStub* (*CreateInvokeStubFn)(bool is_static,
                                                     const char* shorty, uint32_t shorty_len);
-  CreateInvokeStubFn create_invoke_stub_;
+#else
+  typedef CompiledInvokeStub* (*CreateInvokeStubFn)(Compiler& compiler, bool is_static,
+                                                    const char* shorty, uint32_t shorty_len);
 #endif
+  CreateInvokeStubFn create_invoke_stub_;
 
   DISALLOW_COPY_AND_ASSIGN(Compiler);
 };
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 67b3f4d..5a3725e 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -16,8 +16,10 @@
 
 #include "compiler_llvm.h"
 
+#include "class_linker.h"
 #include "compilation_unit.h"
 #include "compiler.h"
+#include "dex_cache.h"
 #include "ir_builder.h"
 #include "jni_compiler.h"
 #include "method_compiler.h"
@@ -207,3 +209,78 @@
 
 } // namespace compiler_llvm
 } // namespace art
+
+namespace {
+
+void ensureCompilerLLVM(art::Compiler& compiler) {
+  if (compiler.GetCompilerLLVM() == NULL) {
+    compiler.SetCompilerLLVM(new art::compiler_llvm::CompilerLLVM(&compiler,
+                                                                  compiler.GetInstructionSet()));
+  }
+  art::compiler_llvm::CompilerLLVM* compiler_llvm = compiler.GetCompilerLLVM();
+  compiler_llvm->SetElfFileName(compiler.GetElfFileName());
+  compiler_llvm->SetBitcodeFileName(compiler.GetBitcodeFileName());
+}
+
+}  // anonymous namespace
+
+extern "C" art::CompiledMethod* oatCompileMethod(art::Compiler& compiler,
+                                                 const art::DexFile::CodeItem* code_item,
+                                                 uint32_t access_flags, uint32_t method_idx,
+                                                 const art::ClassLoader* class_loader,
+                                                 const art::DexFile& dex_file)
+{
+  ensureCompilerLLVM(compiler);
+
+  art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
+  art::DexCache *dex_cache = class_linker->FindDexCache(dex_file);
+
+  art::OatCompilationUnit oat_compilation_unit(
+    class_loader, class_linker, dex_file, *dex_cache, code_item,
+    method_idx, access_flags);
+
+  return compiler.GetCompilerLLVM()->CompileDexMethod(&oat_compilation_unit);
+}
+
+extern "C" art::CompiledMethod* ArtJniCompileMethod(art::Compiler& compiler,
+                                                    uint32_t access_flags, uint32_t method_idx,
+                                                    const art::ClassLoader* class_loader,
+                                                    const art::DexFile& dex_file) {
+  ensureCompilerLLVM(compiler);
+
+  art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
+  art::DexCache *dex_cache = class_linker->FindDexCache(dex_file);
+
+  art::OatCompilationUnit oat_compilation_unit(
+    class_loader, class_linker, dex_file, *dex_cache, NULL,
+    method_idx, access_flags);
+
+  return compiler.GetCompilerLLVM()->CompileNativeMethod(&oat_compilation_unit);
+}
+
+extern "C" art::CompiledInvokeStub* ArtCreateInvokeStub(art::Compiler& compiler, bool is_static,
+                                                        const char* shorty, uint32_t shorty_len) {
+  ensureCompilerLLVM(compiler);
+  //shorty_len = 0; // To make the compiler happy
+  return compiler.GetCompilerLLVM()->CreateInvokeStub(is_static, shorty);
+}
+
+extern "C" void compilerLLVMMaterializeRemainder(art::Compiler& compiler) {
+  ensureCompilerLLVM(compiler);
+  compiler.GetCompilerLLVM()->MaterializeRemainder();
+}
+
+extern "C" void compilerLLVMMaterializeIfThresholdReached(art::Compiler& compiler) {
+  ensureCompilerLLVM(compiler);
+  compiler.GetCompilerLLVM()->MaterializeIfThresholdReached();
+}
+
+// Note: Using this function carefully!!! This is temporary solution, we will remove it.
+extern "C" art::MutexLock* compilerLLVMMutexLock(art::Compiler& compiler) {
+  ensureCompilerLLVM(compiler);
+  return new art::MutexLock(compiler.GetCompilerLLVM()->compiler_lock_);
+}
+
+extern "C" void compilerLLVMDispose(art::Compiler& compiler) {
+  delete compiler.GetCompilerLLVM();
+}