Create separate Android.mk for main build targets

The runtime, compiler, dex2oat, and oatdump now are in seperate trees
to prevent dependency creep.  They can now be individually built
without rebuilding the rest of the art projects. dalvikvm and jdwpspy
were already this way. Builds in the art directory should behave as
before, building everything including tests.

Change-Id: Ic6b1151e5ed0f823c3dd301afd2b13eb2d8feb81
diff --git a/compiler/llvm/art_module.ll b/compiler/llvm/art_module.ll
new file mode 100644
index 0000000..233692c
--- /dev/null
+++ b/compiler/llvm/art_module.ll
@@ -0,0 +1,153 @@
+;;
+;; 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.
+;;
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Type
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+%JavaObject = type opaque
+
+%ShadowFrame = type { i32                  ; Number of VRegs
+                    , %ShadowFrame*        ; Previous frame
+                    , %JavaObject*         ; Method object pointer
+                    , i32                  ; Line number for stack backtrace
+                    ; [0 x i32]            ; VRegs
+                    }
+
+declare void @__art_type_list(%JavaObject*, %ShadowFrame*)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Thread
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+declare %JavaObject* @art_portable_get_current_thread_from_code()
+declare %JavaObject* @art_portable_set_current_thread_from_code(%JavaObject*)
+
+declare void @art_portable_lock_object_from_code(%JavaObject*, %JavaObject*)
+declare void @art_portable_unlock_object_from_code(%JavaObject*, %JavaObject*)
+
+declare void @art_portable_test_suspend_from_code(%JavaObject*)
+
+declare %ShadowFrame* @art_portable_push_shadow_frame_from_code(%JavaObject*, %ShadowFrame*, %JavaObject*, i32)
+declare void @art_portable_pop_shadow_frame_from_code(%ShadowFrame*)
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Exception
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+declare %JavaObject* @art_portable_get_and_clear_exception(%JavaObject*)
+declare void @art_portable_throw_div_zero_from_code()
+declare void @art_portable_throw_array_bounds_from_code(i32, i32)
+declare void @art_portable_throw_no_such_method_from_code(i32)
+declare void @art_portable_throw_null_pointer_exception_from_code(i32)
+declare void @art_portable_throw_stack_overflow_from_code()
+declare void @art_portable_throw_exception_from_code(%JavaObject*)
+
+declare i32 @art_portable_find_catch_block_from_code(%JavaObject*, i32)
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Object Space
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+declare %JavaObject* @art_portable_alloc_object_from_code(i32, %JavaObject*, %JavaObject*)
+declare %JavaObject* @art_portable_alloc_object_from_code_with_access_check(i32, %JavaObject*, %JavaObject*)
+
+declare %JavaObject* @art_portable_alloc_array_from_code(i32, %JavaObject*, i32, %JavaObject*)
+declare %JavaObject* @art_portable_alloc_array_from_code_with_access_check(i32, %JavaObject*, i32, %JavaObject*)
+declare %JavaObject* @art_portable_check_and_alloc_array_from_code(i32, %JavaObject*, i32, %JavaObject*)
+declare %JavaObject* @art_portable_check_and_alloc_array_from_code_with_access_check(i32, %JavaObject*, i32, %JavaObject*)
+
+declare void @art_portable_find_instance_field_from_code(i32, %JavaObject*)
+declare void @art_portable_find_static_field_from_code(i32, %JavaObject*)
+
+declare %JavaObject* @art_portable_find_static_method_from_code_with_access_check(i32, %JavaObject*, %JavaObject*, %JavaObject*)
+declare %JavaObject* @art_portable_find_direct_method_from_code_with_access_check(i32, %JavaObject*, %JavaObject*, %JavaObject*)
+declare %JavaObject* @art_portable_find_virtual_method_from_code_with_access_check(i32, %JavaObject*, %JavaObject*, %JavaObject*)
+declare %JavaObject* @art_portable_find_super_method_from_code_with_access_check(i32, %JavaObject*, %JavaObject*, %JavaObject*)
+declare %JavaObject* @art_portable_find_interface_method_from_code_with_access_check(i32, %JavaObject*, %JavaObject*, %JavaObject*)
+declare %JavaObject* @art_portable_find_interface_method_from_code(i32, %JavaObject*, %JavaObject*, %JavaObject*)
+
+declare %JavaObject* @art_portable_initialize_static_storage_from_code(i32, %JavaObject*, %JavaObject*)
+declare %JavaObject* @art_portable_initialize_type_from_code(i32, %JavaObject*, %JavaObject*)
+declare %JavaObject* @art_portable_initialize_type_and_verify_access_from_code(i32, %JavaObject*, %JavaObject*)
+
+declare %JavaObject* @art_portable_resolve_string_from_code(%JavaObject*, i32)
+
+declare i32 @art_portable_set32_static_from_code(i32, %JavaObject*, i32)
+declare i32 @art_portable_set64_static_from_code(i32, %JavaObject*, i64)
+declare i32 @art_portable_set_obj_static_from_code(i32, %JavaObject*, %JavaObject*)
+
+declare i32 @art_portable_get32_static_from_code(i32, %JavaObject*)
+declare i64 @art_portable_get64_static_from_code(i32, %JavaObject*)
+declare %JavaObject* @art_portable_get_obj_static_from_code(i32, %JavaObject*)
+
+declare i32 @art_portable_set32_instance_from_code(i32, %JavaObject*, %JavaObject*, i32)
+declare i32 @art_portable_set64_instance_from_code(i32, %JavaObject*, %JavaObject*, i64)
+declare i32 @art_portable_set_obj_instance_from_code(i32, %JavaObject*, %JavaObject*, %JavaObject*)
+
+declare i32 @art_portable_get32_instance_from_code(i32, %JavaObject*, %JavaObject*)
+declare i64 @art_portable_get64_instance_from_code(i32, %JavaObject*, %JavaObject*)
+declare %JavaObject* @art_portable_get_obj_instance_from_code(i32, %JavaObject*, %JavaObject*)
+
+declare %JavaObject* @art_portable_decode_jobject_in_thread(%JavaObject*, %JavaObject*)
+
+declare void @art_portable_fill_array_data_from_code(%JavaObject*, i32, %JavaObject*, i32)
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Type Checking, in the nature of casting
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+declare i32 @art_portable_is_assignable_from_code(%JavaObject*, %JavaObject*)
+declare void @art_portable_check_cast_from_code(%JavaObject*, %JavaObject*)
+declare void @art_portable_check_put_array_element_from_code(%JavaObject*, %JavaObject*)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Math
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+declare i64 @art_d2l(double)
+declare i32 @art_d2i(double)
+declare i64 @art_f2l(float)
+declare i32 @art_f2i(float)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; JNI
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+declare i32 @art_portable_jni_method_start(%JavaObject*)
+declare i32 @art_portable_jni_method_start_synchronized(%JavaObject*, %JavaObject*)
+
+declare void @art_portable_jni_method_end(i32, %JavaObject*)
+declare void @art_portable_jni_method_end_synchronized(i32, %JavaObject*, %JavaObject*)
+declare %JavaObject* @art_portable_jni_method_end_with_reference(%JavaObject*, i32, %JavaObject*)
+declare %JavaObject* @art_portable_jni_method_end_with_reference_synchronized(%JavaObject*, i32, %JavaObject*, %JavaObject*)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Temporary runtime support, will be removed in the future
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+declare i1 @art_portable_is_exception_pending_from_code()
+
+declare void @art_portable_mark_gc_card_from_code(%JavaObject*, %JavaObject*)
+
+declare void @art_portable_proxy_invoke_handler_from_code(%JavaObject*, ...)
diff --git a/compiler/llvm/backend_options.h b/compiler/llvm/backend_options.h
new file mode 100644
index 0000000..924a346
--- /dev/null
+++ b/compiler/llvm/backend_options.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_SRC_COMPILER_LLVM_BACKEND_OPTIONS_H_
+#define ART_SRC_COMPILER_LLVM_BACKEND_OPTIONS_H_
+
+#include <llvm/Support/CommandLine.h>
+
+#define DECLARE_ARM_BACKEND_OPTIONS \
+extern llvm::cl::opt<bool> EnableARMLongCalls; \
+extern llvm::cl::opt<bool> ReserveR9;
+
+#define INITIAL_ARM_BACKEND_OPTIONS \
+EnableARMLongCalls = true; \
+ReserveR9 = true;
+
+#define DECLARE_X86_BACKEND_OPTIONS
+#define INITIAL_X86_BACKEND_OPTIONS
+
+#define DECLARE_Mips_BACKEND_OPTIONS
+#define INITIAL_Mips_BACKEND_OPTIONS
+
+#define LLVM_TARGET(TargetName) DECLARE_##TargetName##_BACKEND_OPTIONS
+#include "llvm/Config/Targets.def"
+
+namespace art {
+namespace llvm {
+
+inline void InitialBackendOptions() {
+#define LLVM_TARGET(TargetName) INITIAL_##TargetName##_BACKEND_OPTIONS
+#include "llvm/Config/Targets.def"
+}
+
+}  // namespace llvm
+}  // namespace art
+
+#endif  // ART_SRC_COMPILER_LLVM_BACKEND_OPTIONS_H_
diff --git a/compiler/llvm/backend_types.h b/compiler/llvm/backend_types.h
new file mode 100644
index 0000000..c89504a
--- /dev/null
+++ b/compiler/llvm/backend_types.h
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_SRC_COMPILER_LLVM_BACKEND_TYPES_H_
+#define ART_SRC_COMPILER_LLVM_BACKEND_TYPES_H_
+
+#include "base/logging.h"
+
+
+namespace art {
+namespace llvm {
+
+
+enum JType {
+  kVoid,
+  kBoolean,
+  kByte,
+  kChar,
+  kShort,
+  kInt,
+  kLong,
+  kFloat,
+  kDouble,
+  kObject,
+  MAX_JTYPE
+};
+
+enum TBAASpecialType {
+  kTBAARegister,
+  kTBAAStackTemp,
+  kTBAAHeapArray,
+  kTBAAHeapInstance,
+  kTBAAHeapStatic,
+  kTBAAJRuntime,
+  kTBAARuntimeInfo,
+  kTBAAShadowFrame,
+  kTBAAConstJObject,
+  MAX_TBAA_SPECIAL_TYPE
+};
+
+
+enum ExpectCond {
+  kLikely,
+  kUnlikely,
+  MAX_EXPECT
+};
+
+
+inline JType GetJTypeFromShorty(char shorty_jty) {
+  switch (shorty_jty) {
+  case 'V':
+    return kVoid;
+
+  case 'Z':
+    return kBoolean;
+
+  case 'B':
+    return kByte;
+
+  case 'C':
+    return kChar;
+
+  case 'S':
+    return kShort;
+
+  case 'I':
+    return kInt;
+
+  case 'J':
+    return kLong;
+
+  case 'F':
+    return kFloat;
+
+  case 'D':
+    return kDouble;
+
+  case 'L':
+    return kObject;
+
+  default:
+    LOG(FATAL) << "Unknown Dalvik shorty descriptor: " << shorty_jty;
+    return kVoid;
+  }
+}
+
+} // namespace llvm
+} // namespace art
+
+
+#endif // ART_SRC_COMPILER_LLVM_BACKEND_TYPES_H_
diff --git a/compiler/llvm/compiler_llvm.cc b/compiler/llvm/compiler_llvm.cc
new file mode 100644
index 0000000..afca223
--- /dev/null
+++ b/compiler/llvm/compiler_llvm.cc
@@ -0,0 +1,239 @@
+/*
+ * 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.
+ */
+
+#include "compiler_llvm.h"
+
+#include "backend_options.h"
+#include "base/stl_util.h"
+#include "class_linker.h"
+#include "compiled_method.h"
+#include "driver/compiler_driver.h"
+#include "driver/dex_compilation_unit.h"
+#include "globals.h"
+#include "ir_builder.h"
+#include "jni/portable/jni_compiler.h"
+#include "llvm_compilation_unit.h"
+#include "oat_file.h"
+#include "utils_llvm.h"
+#include "verifier/method_verifier.h"
+
+#include <llvm/LinkAllPasses.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <llvm/Support/TargetSelect.h>
+#include <llvm/Support/Threading.h>
+
+namespace art {
+void CompileOneMethod(CompilerDriver& driver,
+                      const CompilerBackend compilerBackend,
+                      const DexFile::CodeItem* code_item,
+                      uint32_t access_flags, InvokeType invoke_type,
+                      uint32_t class_def_idx, uint32_t method_idx, jobject class_loader,
+                      const DexFile& dex_file,
+                      llvm::LlvmCompilationUnit* llvm_info);
+}
+
+namespace llvm {
+  extern bool TimePassesIsEnabled;
+}
+
+namespace {
+
+pthread_once_t llvm_initialized = PTHREAD_ONCE_INIT;
+
+void InitializeLLVM() {
+  // Initialize LLVM internal data structure for multithreading
+  llvm::llvm_start_multithreaded();
+
+  // NOTE: Uncomment following line to show the time consumption of LLVM passes
+  //llvm::TimePassesIsEnabled = true;
+
+  // Initialize LLVM target-specific options.
+  art::llvm::InitialBackendOptions();
+
+  // Initialize LLVM target, MC subsystem, asm printer, and asm parser.
+  if (art::kIsTargetBuild) {
+    // Don't initialize all targets on device. Just initialize the device's native target
+    llvm::InitializeNativeTarget();
+    llvm::InitializeNativeTargetAsmPrinter();
+    llvm::InitializeNativeTargetAsmParser();
+  } else {
+    llvm::InitializeAllTargets();
+    llvm::InitializeAllTargetMCs();
+    llvm::InitializeAllAsmPrinters();
+    llvm::InitializeAllAsmParsers();
+  }
+
+  // Initialize LLVM optimization passes
+  llvm::PassRegistry &registry = *llvm::PassRegistry::getPassRegistry();
+
+  llvm::initializeCore(registry);
+  llvm::initializeScalarOpts(registry);
+  llvm::initializeIPO(registry);
+  llvm::initializeAnalysis(registry);
+  llvm::initializeIPA(registry);
+  llvm::initializeTransformUtils(registry);
+  llvm::initializeInstCombine(registry);
+  llvm::initializeInstrumentation(registry);
+  llvm::initializeTarget(registry);
+}
+
+// The Guard to Shutdown LLVM
+// llvm::llvm_shutdown_obj llvm_guard;
+// TODO: We are commenting out this line because this will cause SEGV from
+// time to time.
+// Two reasons: (1) the order of the destruction of static objects, or
+//              (2) dlopen/dlclose side-effect on static objects.
+
+} // anonymous namespace
+
+
+namespace art {
+namespace llvm {
+
+
+::llvm::Module* makeLLVMModuleContents(::llvm::Module* module);
+
+
+CompilerLLVM::CompilerLLVM(CompilerDriver* driver, InstructionSet insn_set)
+    : compiler_driver_(driver), insn_set_(insn_set),
+      next_cunit_id_lock_("compilation unit id lock"), next_cunit_id_(1) {
+
+  // Initialize LLVM libraries
+  pthread_once(&llvm_initialized, InitializeLLVM);
+}
+
+
+CompilerLLVM::~CompilerLLVM() {
+}
+
+
+LlvmCompilationUnit* CompilerLLVM::AllocateCompilationUnit() {
+  MutexLock GUARD(Thread::Current(), next_cunit_id_lock_);
+  LlvmCompilationUnit* cunit = new LlvmCompilationUnit(this, next_cunit_id_++);
+  if (!bitcode_filename_.empty()) {
+    cunit->SetBitcodeFileName(StringPrintf("%s-%zu",
+                                           bitcode_filename_.c_str(),
+                                           cunit->GetCompilationUnitId()));
+  }
+  return cunit;
+}
+
+
+CompiledMethod* CompilerLLVM::
+CompileDexMethod(DexCompilationUnit* dex_compilation_unit, InvokeType invoke_type) {
+  UniquePtr<LlvmCompilationUnit> cunit(AllocateCompilationUnit());
+
+  cunit->SetDexCompilationUnit(dex_compilation_unit);
+  cunit->SetCompilerDriver(compiler_driver_);
+  // TODO: consolidate ArtCompileMethods
+  CompileOneMethod(*compiler_driver_,
+                   kPortable,
+                   dex_compilation_unit->GetCodeItem(),
+                   dex_compilation_unit->GetAccessFlags(),
+                   invoke_type,
+                   dex_compilation_unit->GetClassDefIndex(),
+                   dex_compilation_unit->GetDexMethodIndex(),
+                   dex_compilation_unit->GetClassLoader(),
+                   *dex_compilation_unit->GetDexFile(),
+                   cunit.get());
+
+  cunit->Materialize();
+
+  MethodReference mref(dex_compilation_unit->GetDexFile(),
+                       dex_compilation_unit->GetDexMethodIndex());
+  return new CompiledMethod(compiler_driver_->GetInstructionSet(),
+                            cunit->GetElfObject(),
+                            *verifier::MethodVerifier::GetDexGcMap(mref),
+                            cunit->GetDexCompilationUnit()->GetSymbol());
+}
+
+
+CompiledMethod* CompilerLLVM::
+CompileNativeMethod(DexCompilationUnit* dex_compilation_unit) {
+  UniquePtr<LlvmCompilationUnit> cunit(AllocateCompilationUnit());
+
+  UniquePtr<JniCompiler> jni_compiler(
+      new JniCompiler(cunit.get(), *compiler_driver_, dex_compilation_unit));
+
+  return jni_compiler->Compile();
+}
+
+
+} // namespace llvm
+} // namespace art
+
+inline static art::llvm::CompilerLLVM* ContextOf(art::CompilerDriver& driver) {
+  void *compiler_context = driver.GetCompilerContext();
+  CHECK(compiler_context != NULL);
+  return reinterpret_cast<art::llvm::CompilerLLVM*>(compiler_context);
+}
+
+inline static const art::llvm::CompilerLLVM* ContextOf(const art::CompilerDriver& driver) {
+  void *compiler_context = driver.GetCompilerContext();
+  CHECK(compiler_context != NULL);
+  return reinterpret_cast<const art::llvm::CompilerLLVM*>(compiler_context);
+}
+
+extern "C" void ArtInitCompilerContext(art::CompilerDriver& driver) {
+  CHECK(driver.GetCompilerContext() == NULL);
+
+  art::llvm::CompilerLLVM* compiler_llvm = new art::llvm::CompilerLLVM(&driver,
+                                                                       driver.GetInstructionSet());
+
+  driver.SetCompilerContext(compiler_llvm);
+}
+
+extern "C" void ArtUnInitCompilerContext(art::CompilerDriver& driver) {
+  delete ContextOf(driver);
+  driver.SetCompilerContext(NULL);
+}
+extern "C" art::CompiledMethod* ArtCompileMethod(art::CompilerDriver& driver,
+                                                 const art::DexFile::CodeItem* code_item,
+                                                 uint32_t access_flags,
+                                                 art::InvokeType invoke_type,
+                                                 uint32_t class_def_idx,
+                                                 uint32_t method_idx,
+                                                 jobject class_loader,
+                                                 const art::DexFile& dex_file) {
+  UNUSED(class_def_idx);  // TODO: this is used with Compiler::RequiresConstructorBarrier.
+  art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
+
+  art::DexCompilationUnit dex_compilation_unit(
+    NULL, class_loader, class_linker, dex_file, code_item,
+    class_def_idx, method_idx, access_flags);
+  art::llvm::CompilerLLVM* compiler_llvm = ContextOf(driver);
+  art::CompiledMethod* result = compiler_llvm->CompileDexMethod(&dex_compilation_unit, invoke_type);
+  return result;
+}
+
+extern "C" art::CompiledMethod* ArtLLVMJniCompileMethod(art::CompilerDriver& driver,
+                                                        uint32_t access_flags, uint32_t method_idx,
+                                                        const art::DexFile& dex_file) {
+  art::ClassLinker *class_linker = art::Runtime::Current()->GetClassLinker();
+
+  art::DexCompilationUnit dex_compilation_unit(
+    NULL, NULL, class_linker, dex_file, NULL,
+    0, method_idx, access_flags);
+
+  art::llvm::CompilerLLVM* compiler_llvm = ContextOf(driver);
+  art::CompiledMethod* result = compiler_llvm->CompileNativeMethod(&dex_compilation_unit);
+  return result;
+}
+
+extern "C" void compilerLLVMSetBitcodeFileName(art::CompilerDriver& driver,
+                                               std::string const& filename) {
+  ContextOf(driver)->SetBitcodeFileName(filename);
+}
diff --git a/compiler/llvm/compiler_llvm.h b/compiler/llvm/compiler_llvm.h
new file mode 100644
index 0000000..b70ddc5
--- /dev/null
+++ b/compiler/llvm/compiler_llvm.h
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_SRC_COMPILER_LLVM_COMPILER_LLVM_H_
+#define ART_SRC_COMPILER_LLVM_COMPILER_LLVM_H_
+
+#include "base/macros.h"
+#include "dex_file.h"
+#include "driver/compiler_driver.h"
+#include "instruction_set.h"
+#include "mirror/object.h"
+
+#include <UniquePtr.h>
+
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace art {
+  class CompiledMethod;
+  class CompilerDriver;
+  class DexCompilationUnit;
+  namespace mirror {
+    class AbstractMethod;
+    class ClassLoader;
+  }  // namespace mirror
+}  // namespace art
+
+
+namespace llvm {
+  class Function;
+  class LLVMContext;
+  class Module;
+  class PointerType;
+  class StructType;
+  class Type;
+}  // namespace llvm
+
+
+namespace art {
+namespace llvm {
+
+class LlvmCompilationUnit;
+class IRBuilder;
+
+class CompilerLLVM {
+ public:
+  CompilerLLVM(CompilerDriver* driver, InstructionSet insn_set);
+
+  ~CompilerLLVM();
+
+  CompilerDriver* GetCompiler() const {
+    return compiler_driver_;
+  }
+
+  InstructionSet GetInstructionSet() const {
+    return insn_set_;
+  }
+
+  void SetBitcodeFileName(std::string const& filename) {
+    bitcode_filename_ = filename;
+  }
+
+  CompiledMethod* CompileDexMethod(DexCompilationUnit* dex_compilation_unit,
+                                   InvokeType invoke_type);
+
+  CompiledMethod* CompileGBCMethod(DexCompilationUnit* dex_compilation_unit, std::string* func);
+
+  CompiledMethod* CompileNativeMethod(DexCompilationUnit* dex_compilation_unit);
+
+ private:
+  LlvmCompilationUnit* AllocateCompilationUnit();
+
+  CompilerDriver* const compiler_driver_;
+
+  const InstructionSet insn_set_;
+
+  Mutex next_cunit_id_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+  size_t next_cunit_id_ GUARDED_BY(next_cunit_id_lock_);
+
+  std::string bitcode_filename_;
+
+  DISALLOW_COPY_AND_ASSIGN(CompilerLLVM);
+};
+
+
+} // namespace llvm
+} // namespace art
+
+#endif // ART_SRC_COMPILER_LLVM_COMPILER_LLVM_H_
diff --git a/compiler/llvm/gbc_expander.cc b/compiler/llvm/gbc_expander.cc
new file mode 100644
index 0000000..b139e32
--- /dev/null
+++ b/compiler/llvm/gbc_expander.cc
@@ -0,0 +1,3753 @@
+/*
+ * 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.
+ */
+
+#include "dex_file-inl.h"
+#include "driver/compiler_driver.h"
+#include "driver/dex_compilation_unit.h"
+#include "intrinsic_helper.h"
+#include "ir_builder.h"
+#include "method_reference.h"
+#include "mirror/abstract_method.h"
+#include "mirror/array.h"
+#include "mirror/string.h"
+#include "thread.h"
+#include "utils_llvm.h"
+#include "verifier/method_verifier.h"
+
+#include "dex/compiler_ir.h"
+#include "dex/mir_graph.h"
+#include "dex/quick/mir_to_lir.h"
+using art::kMIRIgnoreNullCheck;
+using art::kMIRIgnoreRangeCheck;
+
+#include <llvm/ADT/STLExtras.h>
+#include <llvm/IR/Intrinsics.h>
+#include <llvm/IR/Metadata.h>
+#include <llvm/Pass.h>
+#include <llvm/Support/CFG.h>
+#include <llvm/Support/InstIterator.h>
+
+#include <vector>
+#include <map>
+#include <utility>
+
+using namespace art::llvm;
+
+using art::llvm::IntrinsicHelper;
+
+namespace art {
+extern char RemapShorty(char shortyType);
+};
+
+namespace {
+
+class GBCExpanderPass : public llvm::FunctionPass {
+ private:
+  const IntrinsicHelper& intrinsic_helper_;
+  IRBuilder& irb_;
+
+  llvm::LLVMContext& context_;
+  RuntimeSupportBuilder& rtb_;
+
+ private:
+  llvm::AllocaInst* shadow_frame_;
+  llvm::Value* old_shadow_frame_;
+
+ private:
+  art::CompilerDriver* const driver_;
+
+  const art::DexCompilationUnit* const dex_compilation_unit_;
+
+  llvm::Function* func_;
+
+  std::vector<llvm::BasicBlock*> basic_blocks_;
+
+  std::vector<llvm::BasicBlock*> basic_block_landing_pads_;
+  llvm::BasicBlock* current_bb_;
+  std::map<llvm::BasicBlock*, std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*> > >
+      landing_pad_phi_mapping_;
+  llvm::BasicBlock* basic_block_unwind_;
+
+  // Maps each vreg to its shadow frame address.
+  std::vector<llvm::Value*> shadow_frame_vreg_addresses_;
+
+  bool changed_;
+
+ private:
+  //----------------------------------------------------------------------------
+  // Constant for GBC expansion
+  //----------------------------------------------------------------------------
+  enum IntegerShiftKind {
+    kIntegerSHL,
+    kIntegerSHR,
+    kIntegerUSHR,
+  };
+
+ private:
+  //----------------------------------------------------------------------------
+  // Helper function for GBC expansion
+  //----------------------------------------------------------------------------
+
+  llvm::Value* ExpandToRuntime(runtime_support::RuntimeId rt,
+                               llvm::CallInst& inst);
+
+  uint64_t LV2UInt(llvm::Value* lv) {
+    return llvm::cast<llvm::ConstantInt>(lv)->getZExtValue();
+  }
+
+  int64_t LV2SInt(llvm::Value* lv) {
+    return llvm::cast<llvm::ConstantInt>(lv)->getSExtValue();
+  }
+
+ private:
+  // TODO: Almost all Emit* are directly copy-n-paste from MethodCompiler.
+  // Refactor these utility functions from MethodCompiler to avoid forking.
+
+  void EmitStackOverflowCheck(llvm::Instruction* first_non_alloca);
+
+  void RewriteFunction();
+
+  void RewriteBasicBlock(llvm::BasicBlock* original_block);
+
+  void UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
+                            llvm::BasicBlock* new_basic_block);
+
+
+  // Sign or zero extend category 1 types < 32bits in size to 32bits.
+  llvm::Value* SignOrZeroExtendCat1Types(llvm::Value* value, JType jty);
+
+  // Truncate category 1 types from 32bits to the given JType size.
+  llvm::Value* TruncateCat1Types(llvm::Value* value, JType jty);
+
+  //----------------------------------------------------------------------------
+  // Dex cache code generation helper function
+  //----------------------------------------------------------------------------
+  llvm::Value* EmitLoadDexCacheAddr(art::MemberOffset dex_cache_offset);
+
+  llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
+
+  llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
+
+  llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
+
+  llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
+
+  //----------------------------------------------------------------------------
+  // Code generation helper function
+  //----------------------------------------------------------------------------
+  llvm::Value* EmitLoadMethodObjectAddr();
+
+  llvm::Value* EmitLoadArrayLength(llvm::Value* array);
+
+  llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
+
+  llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
+                                                     llvm::Value* this_addr);
+
+  llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
+                            llvm::Value* index_value,
+                            JType elem_jty);
+
+  //----------------------------------------------------------------------------
+  // Invoke helper function
+  //----------------------------------------------------------------------------
+  llvm::Value* EmitInvoke(llvm::CallInst& call_inst);
+
+  //----------------------------------------------------------------------------
+  // Inlining helper functions
+  //----------------------------------------------------------------------------
+  bool EmitIntrinsic(llvm::CallInst& call_inst, llvm::Value** result);
+
+  bool EmitIntrinsicStringLengthOrIsEmpty(llvm::CallInst& call_inst,
+                                          llvm::Value** result, bool is_empty);
+
+ private:
+  //----------------------------------------------------------------------------
+  // Expand Greenland intrinsics
+  //----------------------------------------------------------------------------
+  void Expand_TestSuspend(llvm::CallInst& call_inst);
+
+  void Expand_MarkGCCard(llvm::CallInst& call_inst);
+
+  llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
+
+  llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
+
+  void Expand_LockObject(llvm::Value* obj);
+
+  void Expand_UnlockObject(llvm::Value* obj);
+
+  llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
+                               llvm::Value* index_value,
+                               JType elem_jty);
+
+  void Expand_ArrayPut(llvm::Value* new_value,
+                       llvm::Value* array_addr,
+                       llvm::Value* index_value,
+                       JType elem_jty);
+
+  void Expand_FilledNewArray(llvm::CallInst& call_inst);
+
+  llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
+                               llvm::Value* is_volatile_value,
+                               llvm::Value* object_addr,
+                               JType field_jty);
+
+  void Expand_IPutFast(llvm::Value* field_offset_value,
+                       llvm::Value* is_volatile_value,
+                       llvm::Value* object_addr,
+                       llvm::Value* new_value,
+                       JType field_jty);
+
+  llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
+                               llvm::Value* field_offset_value,
+                               llvm::Value* is_volatile_value,
+                               JType field_jty);
+
+  void Expand_SPutFast(llvm::Value* static_storage_addr,
+                       llvm::Value* field_offset_value,
+                       llvm::Value* is_volatile_value,
+                       llvm::Value* new_value,
+                       JType field_jty);
+
+  llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
+
+  llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
+
+  llvm::Value*
+  Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
+
+  llvm::Value*
+  Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
+                                           llvm::Value* this_addr);
+
+  llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
+
+  llvm::Value* Expand_DivRem(llvm::CallInst& call_inst, bool is_div, JType op_jty);
+
+  void Expand_AllocaShadowFrame(llvm::Value* num_vregs_value);
+
+  void Expand_SetVReg(llvm::Value* entry_idx, llvm::Value* obj);
+
+  void Expand_PopShadowFrame();
+
+  void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
+
+  //----------------------------------------------------------------------------
+  // Quick
+  //----------------------------------------------------------------------------
+
+  llvm::Value* Expand_FPCompare(llvm::Value* src1_value,
+                                llvm::Value* src2_value,
+                                bool gt_bias);
+
+  llvm::Value* Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value);
+
+  llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
+                                          llvm::Value* cmp_lt);
+
+  llvm::Value* EmitLoadConstantClass(uint32_t dex_pc, uint32_t type_idx);
+  llvm::Value* EmitLoadStaticStorage(uint32_t dex_pc, uint32_t type_idx);
+
+  llvm::Value* Expand_HLIGet(llvm::CallInst& call_inst, JType field_jty);
+  void Expand_HLIPut(llvm::CallInst& call_inst, JType field_jty);
+
+  llvm::Value* Expand_HLSget(llvm::CallInst& call_inst, JType field_jty);
+  void Expand_HLSput(llvm::CallInst& call_inst, JType field_jty);
+
+  llvm::Value* Expand_HLArrayGet(llvm::CallInst& call_inst, JType field_jty);
+  void Expand_HLArrayPut(llvm::CallInst& call_inst, JType field_jty);
+
+  llvm::Value* Expand_ConstString(llvm::CallInst& call_inst);
+  llvm::Value* Expand_ConstClass(llvm::CallInst& call_inst);
+
+  void Expand_MonitorEnter(llvm::CallInst& call_inst);
+  void Expand_MonitorExit(llvm::CallInst& call_inst);
+
+  void Expand_HLCheckCast(llvm::CallInst& call_inst);
+  llvm::Value* Expand_InstanceOf(llvm::CallInst& call_inst);
+
+  llvm::Value* Expand_NewInstance(llvm::CallInst& call_inst);
+
+  llvm::Value* Expand_HLInvoke(llvm::CallInst& call_inst);
+
+  llvm::Value* Expand_OptArrayLength(llvm::CallInst& call_inst);
+  llvm::Value* Expand_NewArray(llvm::CallInst& call_inst);
+  llvm::Value* Expand_HLFilledNewArray(llvm::CallInst& call_inst);
+  void Expand_HLFillArrayData(llvm::CallInst& call_inst);
+
+  llvm::Value* EmitAllocNewArray(uint32_t dex_pc,
+                                 llvm::Value* array_length_value,
+                                 uint32_t type_idx,
+                                 bool is_filled_new_array);
+
+  llvm::Value* EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
+                                                        art::InvokeType invoke_type,
+                                                        llvm::Value* this_addr,
+                                                        uint32_t dex_pc,
+                                                        bool is_fast_path);
+
+  void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
+
+  void EmitUpdateDexPC(uint32_t dex_pc);
+
+  void EmitGuard_DivZeroException(uint32_t dex_pc,
+                                  llvm::Value* denominator,
+                                  JType op_jty);
+
+  void EmitGuard_NullPointerException(uint32_t dex_pc, llvm::Value* object,
+                                      int opt_flags);
+
+  void EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
+                                                llvm::Value* array,
+                                                llvm::Value* index,
+                                                int opt_flags);
+
+  llvm::FunctionType* GetFunctionType(llvm::Type* ret_type, uint32_t method_idx, bool is_static);
+
+  llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
+
+  llvm::BasicBlock* CreateBasicBlockWithDexPC(uint32_t dex_pc,
+                                              const char* postfix);
+
+  int32_t GetTryItemOffset(uint32_t dex_pc);
+
+  llvm::BasicBlock* GetLandingPadBasicBlock(uint32_t dex_pc);
+
+  llvm::BasicBlock* GetUnwindBasicBlock();
+
+  void EmitGuard_ExceptionLandingPad(uint32_t dex_pc);
+
+  void EmitBranchExceptionLandingPad(uint32_t dex_pc);
+
+  //----------------------------------------------------------------------------
+  // Expand Arithmetic Helper Intrinsics
+  //----------------------------------------------------------------------------
+
+  llvm::Value* Expand_IntegerShift(llvm::Value* src1_value,
+                                   llvm::Value* src2_value,
+                                   IntegerShiftKind kind,
+                                   JType op_jty);
+
+ public:
+  static char ID;
+
+  GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
+                  art::CompilerDriver* driver, const art::DexCompilationUnit* dex_compilation_unit)
+      : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
+        context_(irb.getContext()), rtb_(irb.Runtime()),
+        shadow_frame_(NULL), old_shadow_frame_(NULL),
+        driver_(driver),
+        dex_compilation_unit_(dex_compilation_unit),
+        func_(NULL), current_bb_(NULL), basic_block_unwind_(NULL), changed_(false) {}
+
+  bool runOnFunction(llvm::Function& func);
+
+ private:
+  void InsertStackOverflowCheck(llvm::Function& func);
+
+  llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
+                               llvm::CallInst& call_inst);
+
+};
+
+char GBCExpanderPass::ID = 0;
+
+bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
+  VLOG(compiler) << "GBC expansion on " << func.getName().str();
+
+  // Runtime support or stub
+  if (dex_compilation_unit_ == NULL) {
+    return false;
+  }
+
+  // Setup rewrite context
+  shadow_frame_ = NULL;
+  old_shadow_frame_ = NULL;
+  func_ = &func;
+  changed_ = false; // Assume unchanged
+
+  shadow_frame_vreg_addresses_.resize(dex_compilation_unit_->GetCodeItem()->registers_size_, NULL);
+  basic_blocks_.resize(dex_compilation_unit_->GetCodeItem()->insns_size_in_code_units_);
+  basic_block_landing_pads_.resize(dex_compilation_unit_->GetCodeItem()->tries_size_, NULL);
+  basic_block_unwind_ = NULL;
+  for (llvm::Function::iterator bb_iter = func_->begin(), bb_end = func_->end();
+       bb_iter != bb_end;
+       ++bb_iter) {
+    if (bb_iter->begin()->getMetadata("DexOff") == NULL) {
+      continue;
+    }
+    uint32_t dex_pc = LV2UInt(bb_iter->begin()->getMetadata("DexOff")->getOperand(0));
+    basic_blocks_[dex_pc] = bb_iter;
+  }
+
+  // Insert stack overflow check
+  InsertStackOverflowCheck(func); // TODO: Use intrinsic.
+
+  // Rewrite the intrinsics
+  RewriteFunction();
+
+  VERIFY_LLVM_FUNCTION(func);
+
+  return changed_;
+}
+
+void GBCExpanderPass::RewriteBasicBlock(llvm::BasicBlock* original_block) {
+  llvm::BasicBlock* curr_basic_block = original_block;
+
+  llvm::BasicBlock::iterator inst_iter = original_block->begin();
+  llvm::BasicBlock::iterator inst_end = original_block->end();
+
+  while (inst_iter != inst_end) {
+    llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst_iter);
+    IntrinsicHelper::IntrinsicId intr_id = IntrinsicHelper::UnknownId;
+
+    if (call_inst) {
+      llvm::Function* callee_func = call_inst->getCalledFunction();
+      intr_id = intrinsic_helper_.GetIntrinsicId(callee_func);
+    }
+
+    if (intr_id == IntrinsicHelper::UnknownId) {
+      // This is not intrinsic call.  Skip this instruction.
+      ++inst_iter;
+      continue;
+    }
+
+    // Rewrite the intrinsic and change the function
+    changed_ = true;
+    irb_.SetInsertPoint(inst_iter);
+
+    // Expand the intrinsic
+    if (llvm::Value* new_value = ExpandIntrinsic(intr_id, *call_inst)) {
+      inst_iter->replaceAllUsesWith(new_value);
+    }
+
+    // Remove the old intrinsic call instruction
+    llvm::BasicBlock::iterator old_inst = inst_iter++;
+    old_inst->eraseFromParent();
+
+    // Splice the instruction to the new basic block
+    llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
+    if (next_basic_block != curr_basic_block) {
+      next_basic_block->getInstList().splice(
+          irb_.GetInsertPoint(), curr_basic_block->getInstList(),
+          inst_iter, inst_end);
+      curr_basic_block = next_basic_block;
+      inst_end = curr_basic_block->end();
+    }
+  }
+}
+
+
+void GBCExpanderPass::RewriteFunction() {
+  size_t num_basic_blocks = func_->getBasicBlockList().size();
+  // NOTE: We are not using (bb_iter != bb_end) as the for-loop condition,
+  // because we will create new basic block while expanding the intrinsics.
+  // We only want to iterate through the input basic blocks.
+
+  landing_pad_phi_mapping_.clear();
+
+  for (llvm::Function::iterator bb_iter = func_->begin();
+       num_basic_blocks > 0; ++bb_iter, --num_basic_blocks) {
+    // Set insert point to current basic block.
+    irb_.SetInsertPoint(bb_iter);
+
+    current_bb_ = bb_iter;
+
+    // Rewrite the basic block
+    RewriteBasicBlock(bb_iter);
+
+    // Update the phi-instructions in the successor basic block
+    llvm::BasicBlock* last_block = irb_.GetInsertBlock();
+    if (last_block != bb_iter) {
+      UpdatePhiInstruction(bb_iter, last_block);
+    }
+  }
+
+  typedef std::map<llvm::PHINode*, llvm::PHINode*> HandlerPHIMap;
+  HandlerPHIMap handler_phi;
+  // Iterate every used landing pad basic block
+  for (size_t i = 0, ei = basic_block_landing_pads_.size(); i != ei; ++i) {
+    llvm::BasicBlock* lbb = basic_block_landing_pads_[i];
+    if (lbb == NULL) {
+      continue;
+    }
+
+    llvm::TerminatorInst* term_inst = lbb->getTerminator();
+    std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*> >& rewrite_pair
+        = landing_pad_phi_mapping_[lbb];
+    irb_.SetInsertPoint(lbb->begin());
+
+    // Iterate every succeeding basic block (catch block)
+    for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
+         succ_iter != succ_end; ++succ_iter) {
+      llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
+
+      // Iterate every phi instructions in the succeeding basic block
+      for (llvm::BasicBlock::iterator
+           inst_iter = succ_basic_block->begin(),
+           inst_end = succ_basic_block->end();
+           inst_iter != inst_end; ++inst_iter) {
+        llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
+
+        if (!phi) {
+          break; // Meet non-phi instruction.  Done.
+        }
+
+        if (handler_phi[phi] == NULL) {
+          handler_phi[phi] = llvm::PHINode::Create(phi->getType(), 1);
+        }
+
+        // Create new_phi in landing pad
+        llvm::PHINode* new_phi = irb_.CreatePHI(phi->getType(), rewrite_pair.size());
+        // Insert all incoming value into new_phi by rewrite_pair
+        for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
+          llvm::BasicBlock* old_bb = rewrite_pair[j].first;
+          llvm::BasicBlock* new_bb = rewrite_pair[j].second;
+          new_phi->addIncoming(phi->getIncomingValueForBlock(old_bb), new_bb);
+        }
+        // Delete all incoming value from phi by rewrite_pair
+        for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
+          llvm::BasicBlock* old_bb = rewrite_pair[j].first;
+          int old_bb_idx = phi->getBasicBlockIndex(old_bb);
+          if (old_bb_idx >= 0) {
+            phi->removeIncomingValue(old_bb_idx, false);
+          }
+        }
+        // Insert new_phi into new handler phi
+        handler_phi[phi]->addIncoming(new_phi, lbb);
+      }
+    }
+  }
+
+  // Replace all handler phi
+  // We can't just use the old handler phi, because some exception edges will disappear after we
+  // compute fast-path.
+  for (HandlerPHIMap::iterator it = handler_phi.begin(); it != handler_phi.end(); ++it) {
+    llvm::PHINode* old_phi = it->first;
+    llvm::PHINode* new_phi = it->second;
+    new_phi->insertBefore(old_phi);
+    old_phi->replaceAllUsesWith(new_phi);
+    old_phi->eraseFromParent();
+  }
+}
+
+void GBCExpanderPass::UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
+                                           llvm::BasicBlock* new_basic_block) {
+  llvm::TerminatorInst* term_inst = new_basic_block->getTerminator();
+
+  if (!term_inst) {
+    return; // No terminating instruction in new_basic_block.  Nothing to do.
+  }
+
+  // Iterate every succeeding basic block
+  for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
+       succ_iter != succ_end; ++succ_iter) {
+    llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
+
+    // Iterate every phi instructions in the succeeding basic block
+    for (llvm::BasicBlock::iterator
+         inst_iter = succ_basic_block->begin(),
+         inst_end = succ_basic_block->end();
+         inst_iter != inst_end; ++inst_iter) {
+      llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
+
+      if (!phi) {
+        break; // Meet non-phi instruction.  Done.
+      }
+
+      // Update the incoming block of this phi instruction
+      for (llvm::PHINode::block_iterator
+           ibb_iter = phi->block_begin(), ibb_end = phi->block_end();
+           ibb_iter != ibb_end; ++ibb_iter) {
+        if (*ibb_iter == old_basic_block) {
+          *ibb_iter = new_basic_block;
+        }
+      }
+    }
+  }
+}
+
+llvm::Value* GBCExpanderPass::ExpandToRuntime(runtime_support::RuntimeId rt,
+                                              llvm::CallInst& inst) {
+  // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
+  // the arguments passed to the GBC intrinsic are as the same as IBC runtime
+  // function, therefore only called function is needed to change.
+  unsigned num_args = inst.getNumArgOperands();
+
+  if (num_args <= 0) {
+    return irb_.CreateCall(irb_.GetRuntime(rt));
+  } else {
+    std::vector<llvm::Value*> args;
+    for (unsigned i = 0; i < num_args; i++) {
+      args.push_back(inst.getArgOperand(i));
+    }
+
+    return irb_.CreateCall(irb_.GetRuntime(rt), args);
+  }
+}
+
+void
+GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
+  llvm::Function* func = first_non_alloca->getParent()->getParent();
+  llvm::Module* module = func->getParent();
+
+  // Call llvm intrinsic function to get frame address.
+  llvm::Function* frameaddress =
+      llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
+
+  // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
+  llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
+
+  // Cast i8* to int
+  frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
+
+  // Get thread.stack_end_
+  llvm::Value* stack_end =
+    irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::StackEndOffset().Int32Value(),
+                                            irb_.getPtrEquivIntTy(),
+                                            kTBAARuntimeInfo);
+
+  // Check the frame address < thread.stack_end_ ?
+  llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
+
+  llvm::BasicBlock* block_exception =
+      llvm::BasicBlock::Create(context_, "stack_overflow", func);
+
+  llvm::BasicBlock* block_continue =
+      llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
+
+  irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
+
+  // If stack overflow, throw exception.
+  irb_.SetInsertPoint(block_exception);
+  irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowStackOverflowException));
+
+  // Unwind.
+  llvm::Type* ret_type = func->getReturnType();
+  if (ret_type->isVoidTy()) {
+    irb_.CreateRetVoid();
+  } else {
+    // The return value is ignored when there's an exception. MethodCompiler
+    // returns zero value under the the corresponding return type  in this case.
+    // GBCExpander returns LLVM undef value here for brevity
+    irb_.CreateRet(llvm::UndefValue::get(ret_type));
+  }
+
+  irb_.SetInsertPoint(block_continue);
+}
+
+llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(art::MemberOffset offset) {
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  return irb_.LoadFromObjectOffset(method_object_addr,
+                                   offset.Int32Value(),
+                                   irb_.getJObjectTy(),
+                                   kTBAAConstJObject);
+}
+
+llvm::Value*
+GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
+  llvm::Value* static_storage_dex_cache_addr =
+    EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset());
+
+  llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
+
+  return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
+}
+
+llvm::Value*
+GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
+  llvm::Value* resolved_type_dex_cache_addr =
+    EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedTypesOffset());
+
+  llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
+
+  return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
+}
+
+llvm::Value* GBCExpanderPass::
+EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
+  llvm::Value* resolved_method_dex_cache_addr =
+    EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedMethodsOffset());
+
+  llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
+
+  return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
+}
+
+llvm::Value* GBCExpanderPass::
+EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
+  llvm::Value* string_dex_cache_addr =
+    EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheStringsOffset());
+
+  llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
+
+  return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
+}
+
+llvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
+  llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
+  return parent_func->arg_begin();
+}
+
+llvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
+  // Load array length
+  return irb_.LoadFromObjectOffset(array,
+                                   art::mirror::Array::LengthOffset().Int32Value(),
+                                   irb_.getJIntTy(),
+                                   kTBAAConstJObject);
+
+}
+
+llvm::Value*
+GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
+  llvm::Value* callee_method_object_field_addr =
+    EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
+
+  return irb_.CreateLoad(callee_method_object_field_addr, kTBAARuntimeInfo);
+}
+
+llvm::Value* GBCExpanderPass::
+EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
+  // Load class object of *this* pointer
+  llvm::Value* class_object_addr =
+    irb_.LoadFromObjectOffset(this_addr,
+                              art::mirror::Object::ClassOffset().Int32Value(),
+                              irb_.getJObjectTy(),
+                              kTBAAConstJObject);
+
+  // Load vtable address
+  llvm::Value* vtable_addr =
+    irb_.LoadFromObjectOffset(class_object_addr,
+                              art::mirror::Class::VTableOffset().Int32Value(),
+                              irb_.getJObjectTy(),
+                              kTBAAConstJObject);
+
+  // Load callee method object
+  llvm::Value* vtable_idx_value =
+    irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
+
+  llvm::Value* method_field_addr =
+    EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
+
+  return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
+}
+
+// Emit Array GetElementPtr
+llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
+                                           llvm::Value* index_value,
+                                           JType elem_jty) {
+
+  int data_offset;
+  if (elem_jty == kLong || elem_jty == kDouble ||
+      (elem_jty == kObject && sizeof(uint64_t) == sizeof(art::mirror::Object*))) {
+    data_offset = art::mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
+  } else {
+    data_offset = art::mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
+  }
+
+  llvm::Constant* data_offset_value =
+    irb_.getPtrEquivInt(data_offset);
+
+  llvm::Type* elem_type = irb_.getJType(elem_jty);
+
+  llvm::Value* array_data_addr =
+    irb_.CreatePtrDisp(array_addr, data_offset_value,
+                       elem_type->getPointerTo());
+
+  return irb_.CreateGEP(array_data_addr, index_value);
+}
+
+llvm::Value* GBCExpanderPass::EmitInvoke(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  art::InvokeType invoke_type =
+      static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
+  bool is_static = (invoke_type == art::kStatic);
+  art::MethodReference target_method(dex_compilation_unit_->GetDexFile(),
+                                     LV2UInt(call_inst.getArgOperand(1)));
+
+  // Load *this* actual parameter
+  llvm::Value* this_addr = (!is_static) ? call_inst.getArgOperand(3) : NULL;
+
+  // Compute invoke related information for compiler decision
+  int vtable_idx = -1;
+  uintptr_t direct_code = 0;
+  uintptr_t direct_method = 0;
+  bool is_fast_path = driver_->ComputeInvokeInfo(dex_compilation_unit_, dex_pc,
+                                                 invoke_type, target_method,
+                                                 vtable_idx,
+                                                 direct_code, direct_method,
+                                                 true);
+  // Load the method object
+  llvm::Value* callee_method_object_addr = NULL;
+
+  if (!is_fast_path) {
+    callee_method_object_addr =
+        EmitCallRuntimeForCalleeMethodObjectAddr(target_method.dex_method_index, invoke_type,
+                                                 this_addr, dex_pc, is_fast_path);
+  } else {
+    switch (invoke_type) {
+      case art::kStatic:
+      case art::kDirect:
+        if (direct_method != 0u &&
+            direct_method != static_cast<uintptr_t>(-1)) {
+          callee_method_object_addr =
+              irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_method),
+                                  irb_.getJObjectTy());
+        } else {
+          callee_method_object_addr =
+              EmitLoadSDCalleeMethodObjectAddr(target_method.dex_method_index);
+        }
+        break;
+
+      case art::kVirtual:
+        DCHECK(vtable_idx != -1);
+        callee_method_object_addr =
+            EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
+        break;
+
+      case art::kSuper:
+        LOG(FATAL) << "invoke-super should be promoted to invoke-direct in "
+        "the fast path.";
+        break;
+
+      case art::kInterface:
+        callee_method_object_addr =
+            EmitCallRuntimeForCalleeMethodObjectAddr(target_method.dex_method_index,
+                                                     invoke_type, this_addr,
+                                                     dex_pc, is_fast_path);
+        break;
+    }
+  }
+
+  // Load the actual parameter
+  std::vector<llvm::Value*> args;
+
+  args.push_back(callee_method_object_addr); // method object for callee
+
+  for (uint32_t i = 3; i < call_inst.getNumArgOperands(); ++i) {
+    args.push_back(call_inst.getArgOperand(i));
+  }
+
+  llvm::Value* code_addr;
+  llvm::Type* func_type = GetFunctionType(call_inst.getType(),
+                                          target_method.dex_method_index, is_static);
+  if (direct_code != 0u && direct_code != static_cast<uintptr_t>(-1)) {
+    code_addr =
+        irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_code),
+                            func_type->getPointerTo());
+  } else {
+    code_addr =
+        irb_.LoadFromObjectOffset(callee_method_object_addr,
+                                  art::mirror::AbstractMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
+                                  func_type->getPointerTo(), kTBAARuntimeInfo);
+  }
+
+  // Invoke callee
+  EmitUpdateDexPC(dex_pc);
+  llvm::Value* retval = irb_.CreateCall(code_addr, args);
+  EmitGuard_ExceptionLandingPad(dex_pc);
+
+  return retval;
+}
+
+bool GBCExpanderPass::EmitIntrinsic(llvm::CallInst& call_inst,
+                                    llvm::Value** result) {
+  DCHECK(result != NULL);
+
+  uint32_t callee_method_idx = LV2UInt(call_inst.getArgOperand(1));
+  std::string callee_method_name(
+      PrettyMethod(callee_method_idx, *dex_compilation_unit_->GetDexFile()));
+
+  if (callee_method_name == "int java.lang.String.length()") {
+    return EmitIntrinsicStringLengthOrIsEmpty(call_inst, result,
+                                              false /* is_empty */);
+  }
+  if (callee_method_name == "boolean java.lang.String.isEmpty()") {
+    return EmitIntrinsicStringLengthOrIsEmpty(call_inst, result,
+                                              true /* is_empty */);
+  }
+
+  *result = NULL;
+  return false;
+}
+
+bool GBCExpanderPass::EmitIntrinsicStringLengthOrIsEmpty(llvm::CallInst& call_inst,
+                                                         llvm::Value** result,
+                                                         bool is_empty) {
+  art::InvokeType invoke_type =
+        static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
+  DCHECK_NE(invoke_type, art::kStatic);
+  DCHECK_EQ(call_inst.getNumArgOperands(), 4U);
+
+  llvm::Value* this_object = call_inst.getArgOperand(3);
+  llvm::Value* string_count =
+      irb_.LoadFromObjectOffset(this_object,
+                                art::mirror::String::CountOffset().Int32Value(),
+                                irb_.getJIntTy(),
+                                kTBAAConstJObject);
+  if (is_empty) {
+    llvm::Value* count_equals_zero = irb_.CreateICmpEQ(string_count,
+                                                       irb_.getJInt(0));
+    llvm::Value* is_empty = irb_.CreateSelect(count_equals_zero,
+                                              irb_.getJBoolean(true),
+                                              irb_.getJBoolean(false));
+    is_empty = SignOrZeroExtendCat1Types(is_empty, kBoolean);
+    *result = is_empty;
+  } else {
+    *result = string_count;
+  }
+  return true;
+}
+
+void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+
+  llvm::Value* suspend_count =
+      irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::ThreadFlagsOffset().Int32Value(),
+                                              irb_.getInt16Ty(),
+                                              kTBAARuntimeInfo);
+  llvm::Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
+
+  llvm::BasicBlock* basic_block_suspend = CreateBasicBlockWithDexPC(dex_pc, "suspend");
+  llvm::BasicBlock* basic_block_cont = CreateBasicBlockWithDexPC(dex_pc, "suspend_cont");
+
+  irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
+
+  irb_.SetInsertPoint(basic_block_suspend);
+  if (dex_pc != art::DexFile::kDexNoIndex) {
+    EmitUpdateDexPC(dex_pc);
+  }
+  irb_.Runtime().EmitTestSuspend();
+
+  llvm::BasicBlock* basic_block_exception = CreateBasicBlockWithDexPC(dex_pc, "exception");
+  llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
+  irb_.CreateCondBr(exception_pending, basic_block_exception, basic_block_cont, kUnlikely);
+
+  irb_.SetInsertPoint(basic_block_exception);
+  llvm::Type* ret_type = call_inst.getParent()->getParent()->getReturnType();
+  if (ret_type->isVoidTy()) {
+    irb_.CreateRetVoid();
+  } else {
+    // The return value is ignored when there's an exception.
+    irb_.CreateRet(llvm::UndefValue::get(ret_type));
+  }
+
+  irb_.SetInsertPoint(basic_block_cont);
+  return;
+}
+
+void GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
+  irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
+  return;
+}
+
+llvm::Value*
+GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
+  uint32_t string_idx =
+    llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
+
+  llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
+
+  return irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
+}
+
+llvm::Value*
+GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
+  uint32_t type_idx =
+    llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
+
+  llvm::Value* type_field_addr =
+    EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
+
+  return irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
+}
+
+void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
+  rtb_.EmitLockObject(obj);
+  return;
+}
+
+void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
+  rtb_.EmitUnlockObject(obj);
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
+                                              llvm::Value* index_value,
+                                              JType elem_jty) {
+  llvm::Value* array_elem_addr =
+    EmitArrayGEP(array_addr, index_value, elem_jty);
+
+  return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
+}
+
+void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
+                                      llvm::Value* array_addr,
+                                      llvm::Value* index_value,
+                                      JType elem_jty) {
+  llvm::Value* array_elem_addr =
+    EmitArrayGEP(array_addr, index_value, elem_jty);
+
+  irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
+
+  return;
+}
+
+void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
+  // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
+  llvm::Value* array = call_inst.getArgOperand(0);
+
+  uint32_t element_jty =
+    llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
+
+  DCHECK(call_inst.getNumArgOperands() > 2);
+  unsigned num_elements = (call_inst.getNumArgOperands() - 2);
+
+  bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
+
+  uint32_t alignment;
+  llvm::Constant* elem_size;
+  llvm::PointerType* field_type;
+
+  // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
+  // as the element, thus we are only checking 2 cases: primitive int and
+  // non-primitive type.
+  if (is_elem_int_ty) {
+    alignment = sizeof(int32_t);
+    elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
+    field_type = irb_.getJIntTy()->getPointerTo();
+  } else {
+    alignment = irb_.getSizeOfPtrEquivInt();
+    elem_size = irb_.getSizeOfPtrEquivIntValue();
+    field_type = irb_.getJObjectTy()->getPointerTo();
+  }
+
+  llvm::Value* data_field_offset =
+    irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
+
+  llvm::Value* data_field_addr =
+    irb_.CreatePtrDisp(array, data_field_offset, field_type);
+
+  for (unsigned i = 0; i < num_elements; ++i) {
+    // Values to fill the array begin at the 3rd argument
+    llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
+
+    irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
+
+    data_field_addr =
+      irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
+  }
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
+                                              llvm::Value* /*is_volatile_value*/,
+                                              llvm::Value* object_addr,
+                                              JType field_jty) {
+  int field_offset =
+    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
+
+  DCHECK_GE(field_offset, 0);
+
+  llvm::PointerType* field_type =
+    irb_.getJType(field_jty)->getPointerTo();
+
+  field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+  llvm::Value* field_addr =
+    irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
+
+  // TODO: Check is_volatile.  We need to generate atomic load instruction
+  // when is_volatile is true.
+  return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
+}
+
+void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
+                                      llvm::Value* /* is_volatile_value */,
+                                      llvm::Value* object_addr,
+                                      llvm::Value* new_value,
+                                      JType field_jty) {
+  int field_offset =
+    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
+
+  DCHECK_GE(field_offset, 0);
+
+  llvm::PointerType* field_type =
+    irb_.getJType(field_jty)->getPointerTo();
+
+  field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+  llvm::Value* field_addr =
+    irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
+
+  // TODO: Check is_volatile.  We need to generate atomic store instruction
+  // when is_volatile is true.
+  irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
+                                              llvm::Value* field_offset_value,
+                                              llvm::Value* /*is_volatile_value*/,
+                                              JType field_jty) {
+  int field_offset =
+    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
+
+  DCHECK_GE(field_offset, 0);
+
+  llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+  llvm::Value* static_field_addr =
+    irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
+                       irb_.getJType(field_jty)->getPointerTo());
+
+  // TODO: Check is_volatile.  We need to generate atomic store instruction
+  // when is_volatile is true.
+  return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
+}
+
+void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
+                                      llvm::Value* field_offset_value,
+                                      llvm::Value* /* is_volatile_value */,
+                                      llvm::Value* new_value,
+                                      JType field_jty) {
+  int field_offset =
+    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
+
+  DCHECK_GE(field_offset, 0);
+
+  llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+  llvm::Value* static_field_addr =
+    irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
+                       irb_.getJType(field_jty)->getPointerTo());
+
+  // TODO: Check is_volatile.  We need to generate atomic store instruction
+  // when is_volatile is true.
+  irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
+
+  return;
+}
+
+llvm::Value*
+GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
+  return irb_.LoadFromObjectOffset(method_object_addr,
+                                   art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
+                                   irb_.getJObjectTy(),
+                                   kTBAAConstJObject);
+}
+
+llvm::Value*
+GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
+  uint32_t type_idx =
+    llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
+
+  llvm::Value* storage_field_addr =
+    EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
+
+  return irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
+}
+
+llvm::Value*
+GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
+  uint32_t callee_method_idx =
+    llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
+
+  return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
+}
+
+llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
+    llvm::Value* vtable_idx_value,
+    llvm::Value* this_addr) {
+  int vtable_idx =
+    llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
+
+  return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
+}
+
+llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
+  // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
+  llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
+  unsigned num_args = call_inst.getNumArgOperands();
+  llvm::Type* ret_type = call_inst.getType();
+
+  // Determine the function type of the callee method
+  std::vector<llvm::Type*> args_type;
+  std::vector<llvm::Value*> args;
+  for (unsigned i = 0; i < num_args; i++) {
+    args.push_back(call_inst.getArgOperand(i));
+    args_type.push_back(args[i]->getType());
+  }
+
+  llvm::FunctionType* callee_method_type =
+    llvm::FunctionType::get(ret_type, args_type, false);
+
+  llvm::Value* code_addr =
+    irb_.LoadFromObjectOffset(callee_method_object_addr,
+                              art::mirror::AbstractMethod::GetEntryPointFromCompiledCodeOffset().Int32Value(),
+                              callee_method_type->getPointerTo(),
+                              kTBAARuntimeInfo);
+
+  // Invoke callee
+  llvm::Value* retval = irb_.CreateCall(code_addr, args);
+
+  return retval;
+}
+
+llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::CallInst& call_inst,
+                                            bool is_div, JType op_jty) {
+  llvm::Value* dividend = call_inst.getArgOperand(0);
+  llvm::Value* divisor = call_inst.getArgOperand(1);
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  EmitGuard_DivZeroException(dex_pc, divisor, op_jty);
+  // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
+
+  // Check the special case: MININT / -1 = MININT
+  // That case will cause overflow, which is undefined behavior in llvm.
+  // So we check the divisor is -1 or not, if the divisor is -1, we do
+  // the special path to avoid undefined behavior.
+  llvm::Type* op_type = irb_.getJType(op_jty);
+  llvm::Value* zero = irb_.getJZero(op_jty);
+  llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
+
+  llvm::Function* parent = irb_.GetInsertBlock()->getParent();
+  llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
+  llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
+  llvm::BasicBlock* neg_one_cont =
+    llvm::BasicBlock::Create(context_, "", parent);
+
+  llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
+  irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
+
+  // If divisor == -1
+  irb_.SetInsertPoint(eq_neg_one);
+  llvm::Value* eq_result;
+  if (is_div) {
+    // We can just change from "dividend div -1" to "neg dividend". The sub
+    // don't care the sign/unsigned because of two's complement representation.
+    // And the behavior is what we want:
+    //  -(2^n)        (2^n)-1
+    //  MININT  < k <= MAXINT    ->     mul k -1  =  -k
+    //  MININT == k              ->     mul k -1  =   k
+    //
+    // LLVM use sub to represent 'neg'
+    eq_result = irb_.CreateSub(zero, dividend);
+  } else {
+    // Everything modulo -1 will be 0.
+    eq_result = zero;
+  }
+  irb_.CreateBr(neg_one_cont);
+
+  // If divisor != -1, just do the division.
+  irb_.SetInsertPoint(ne_neg_one);
+  llvm::Value* ne_result;
+  if (is_div) {
+    ne_result = irb_.CreateSDiv(dividend, divisor);
+  } else {
+    ne_result = irb_.CreateSRem(dividend, divisor);
+  }
+  irb_.CreateBr(neg_one_cont);
+
+  irb_.SetInsertPoint(neg_one_cont);
+  llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
+  result->addIncoming(eq_result, eq_neg_one);
+  result->addIncoming(ne_result, ne_neg_one);
+
+  return result;
+}
+
+void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_vregs_value) {
+  // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
+  // MethodCompiler::EmitPushShadowFrame
+  uint16_t num_vregs =
+    llvm::cast<llvm::ConstantInt>(num_vregs_value)->getZExtValue();
+
+  llvm::StructType* shadow_frame_type =
+    irb_.getShadowFrameTy(num_vregs);
+
+  // Create allocas at the start of entry block.
+  llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
+  llvm::BasicBlock* entry_block = &func_->front();
+  irb_.SetInsertPoint(&entry_block->front());
+
+  shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
+
+  // Alloca a pointer to old shadow frame
+  old_shadow_frame_ =
+    irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
+
+  irb_.restoreIP(irb_ip_original);
+
+  // Push the shadow frame
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  llvm::Value* shadow_frame_upcast =
+    irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
+
+  llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
+                                                 method_object_addr,
+                                                 num_vregs);
+
+  irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
+
+  return;
+}
+
+void GBCExpanderPass::Expand_SetVReg(llvm::Value* entry_idx,
+                                     llvm::Value* value) {
+  unsigned vreg_idx = LV2UInt(entry_idx);
+  DCHECK_LT(vreg_idx, dex_compilation_unit_->GetCodeItem()->registers_size_);
+
+  llvm::Value* vreg_addr = shadow_frame_vreg_addresses_[vreg_idx];
+  if (UNLIKELY(vreg_addr == NULL)) {
+    DCHECK(shadow_frame_ != NULL);
+
+    llvm::Value* gep_index[] = {
+      irb_.getInt32(0), // No pointer displacement
+      irb_.getInt32(1), // VRegs
+      entry_idx // Pointer field
+    };
+
+    // A shadow frame address must dominate every use in the function so we
+    // place it in the entry block right after the allocas.
+    llvm::BasicBlock::iterator first_non_alloca = func_->getEntryBlock().begin();
+    while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
+      ++first_non_alloca;
+    }
+
+    llvm::IRBuilderBase::InsertPoint ip = irb_.saveIP();
+    irb_.SetInsertPoint(static_cast<llvm::Instruction*>(first_non_alloca));
+    vreg_addr = irb_.CreateGEP(shadow_frame_, gep_index);
+    shadow_frame_vreg_addresses_[vreg_idx] = vreg_addr;
+    irb_.restoreIP(ip);
+  }
+
+  irb_.CreateStore(value,
+                   irb_.CreateBitCast(vreg_addr, value->getType()->getPointerTo()),
+                   kTBAAShadowFrame);
+  return;
+}
+
+void GBCExpanderPass::Expand_PopShadowFrame() {
+  if (old_shadow_frame_ == NULL) {
+    return;
+  }
+  rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
+  return;
+}
+
+void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
+  irb_.StoreToObjectOffset(shadow_frame_,
+                           art::ShadowFrame::DexPCOffset(),
+                           dex_pc_value,
+                           kTBAAShadowFrame);
+  return;
+}
+
+void GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
+  // All alloca instructions are generated in the first basic block of the
+  // function, and there are no alloca instructions after the first non-alloca
+  // instruction.
+
+  llvm::BasicBlock* first_basic_block = &func.front();
+
+  // Look for first non-alloca instruction
+  llvm::BasicBlock::iterator first_non_alloca = first_basic_block->begin();
+  while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
+    ++first_non_alloca;
+  }
+
+  irb_.SetInsertPoint(first_non_alloca);
+
+  // Insert stack overflow check codes before first_non_alloca (i.e., after all
+  // alloca instructions)
+  EmitStackOverflowCheck(&*first_non_alloca);
+
+  irb_.Runtime().EmitTestSuspend();
+
+  llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
+  if (next_basic_block != first_basic_block) {
+    // Splice the rest of the instruction to the continuing basic block
+    next_basic_block->getInstList().splice(
+        irb_.GetInsertPoint(), first_basic_block->getInstList(),
+        first_non_alloca, first_basic_block->end());
+
+    // Rewrite the basic block
+    RewriteBasicBlock(next_basic_block);
+
+    // Update the phi-instructions in the successor basic block
+    UpdatePhiInstruction(first_basic_block, irb_.GetInsertBlock());
+  }
+
+  // We have changed the basic block
+  changed_ = true;
+}
+
+// ==== High-level intrinsic expander ==========================================
+
+llvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
+                                               llvm::Value* src2_value,
+                                               bool gt_bias) {
+  llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
+  llvm::Value* cmp_lt;
+
+  if (gt_bias) {
+    cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
+  } else {
+    cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
+  }
+
+  return EmitCompareResultSelection(cmp_eq, cmp_lt);
+}
+
+llvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
+  llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
+  llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
+
+  return EmitCompareResultSelection(cmp_eq, cmp_lt);
+}
+
+llvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
+                                                         llvm::Value* cmp_lt) {
+
+  llvm::Constant* zero = irb_.getJInt(0);
+  llvm::Constant* pos1 = irb_.getJInt(1);
+  llvm::Constant* neg1 = irb_.getJInt(-1);
+
+  llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
+  llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
+
+  return result_eq;
+}
+
+llvm::Value* GBCExpanderPass::Expand_IntegerShift(llvm::Value* src1_value,
+                                                  llvm::Value* src2_value,
+                                                  IntegerShiftKind kind,
+                                                  JType op_jty) {
+  DCHECK(op_jty == kInt || op_jty == kLong);
+
+  // Mask and zero-extend RHS properly
+  if (op_jty == kInt) {
+    src2_value = irb_.CreateAnd(src2_value, 0x1f);
+  } else {
+    llvm::Value* masked_src2_value = irb_.CreateAnd(src2_value, 0x3f);
+    src2_value = irb_.CreateZExt(masked_src2_value, irb_.getJLongTy());
+  }
+
+  // Create integer shift llvm instruction
+  switch (kind) {
+  case kIntegerSHL:
+    return irb_.CreateShl(src1_value, src2_value);
+
+  case kIntegerSHR:
+    return irb_.CreateAShr(src1_value, src2_value);
+
+  case kIntegerUSHR:
+    return irb_.CreateLShr(src1_value, src2_value);
+
+  default:
+    LOG(FATAL) << "Unknown integer shift kind: " << kind;
+    return NULL;
+  }
+}
+
+llvm::Value* GBCExpanderPass::SignOrZeroExtendCat1Types(llvm::Value* value, JType jty) {
+  switch (jty) {
+    case kBoolean:
+    case kChar:
+      return irb_.CreateZExt(value, irb_.getJType(kInt));
+    case kByte:
+    case kShort:
+      return irb_.CreateSExt(value, irb_.getJType(kInt));
+    case kVoid:
+    case kInt:
+    case kLong:
+    case kFloat:
+    case kDouble:
+    case kObject:
+      return value;  // Nothing to do.
+    default:
+      LOG(FATAL) << "Unknown java type: " << jty;
+      return NULL;
+  }
+}
+
+llvm::Value* GBCExpanderPass::TruncateCat1Types(llvm::Value* value, JType jty) {
+  switch (jty) {
+    case kBoolean:
+    case kChar:
+    case kByte:
+    case kShort:
+      return irb_.CreateTrunc(value, irb_.getJType(jty));
+    case kVoid:
+    case kInt:
+    case kLong:
+    case kFloat:
+    case kDouble:
+    case kObject:
+      return value;  // Nothing to do.
+    default:
+      LOG(FATAL) << "Unknown java type: " << jty;
+      return NULL;
+  }
+}
+
+llvm::Value* GBCExpanderPass::Expand_HLArrayGet(llvm::CallInst& call_inst,
+                                                JType elem_jty) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  llvm::Value* array_addr = call_inst.getArgOperand(1);
+  llvm::Value* index_value = call_inst.getArgOperand(2);
+  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
+
+  EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
+  EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value,
+                                           opt_flags);
+
+  llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
+
+  llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
+
+  return SignOrZeroExtendCat1Types(array_elem_value, elem_jty);
+}
+
+
+void GBCExpanderPass::Expand_HLArrayPut(llvm::CallInst& call_inst,
+                                        JType elem_jty) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  llvm::Value* new_value = call_inst.getArgOperand(1);
+  llvm::Value* array_addr = call_inst.getArgOperand(2);
+  llvm::Value* index_value = call_inst.getArgOperand(3);
+  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
+
+  EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
+  EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value,
+                                           opt_flags);
+
+  new_value = TruncateCat1Types(new_value, elem_jty);
+
+  llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
+
+  if (elem_jty == kObject) { // If put an object, check the type, and mark GC card table.
+    llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::CheckPutArrayElement);
+
+    irb_.CreateCall2(runtime_func, new_value, array_addr);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+    EmitMarkGCCard(new_value, array_addr);
+  }
+
+  irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_HLIGet(llvm::CallInst& call_inst,
+                                            JType field_jty) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  llvm::Value* object_addr = call_inst.getArgOperand(1);
+  uint32_t field_idx = LV2UInt(call_inst.getArgOperand(2));
+  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
+
+  EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
+
+  llvm::Value* field_value;
+
+  int field_offset;
+  bool is_volatile;
+  bool is_fast_path = driver_->ComputeInstanceFieldInfo(
+    field_idx, dex_compilation_unit_, field_offset, is_volatile, false);
+
+  if (!is_fast_path) {
+    llvm::Function* runtime_func;
+
+    if (field_jty == kObject) {
+      runtime_func = irb_.GetRuntime(runtime_support::GetObjectInstance);
+    } else if (field_jty == kLong || field_jty == kDouble) {
+      runtime_func = irb_.GetRuntime(runtime_support::Get64Instance);
+    } else {
+      runtime_func = irb_.GetRuntime(runtime_support::Get32Instance);
+    }
+
+    llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    EmitUpdateDexPC(dex_pc);
+
+    field_value = irb_.CreateCall3(runtime_func, field_idx_value,
+                                   method_object_addr, object_addr);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+    if (field_jty == kFloat || field_jty == kDouble) {
+      field_value = irb_.CreateBitCast(field_value, irb_.getJType(field_jty));
+    }
+  } else {
+    DCHECK_GE(field_offset, 0);
+
+    llvm::PointerType* field_type =
+      irb_.getJType(field_jty)->getPointerTo();
+
+    llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+    llvm::Value* field_addr =
+      irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
+
+    field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
+    field_value = SignOrZeroExtendCat1Types(field_value, field_jty);
+
+    if (is_volatile) {
+      irb_.CreateMemoryBarrier(art::kLoadLoad);
+    }
+  }
+
+  return field_value;
+}
+
+void GBCExpanderPass::Expand_HLIPut(llvm::CallInst& call_inst,
+                                    JType field_jty) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  llvm::Value* new_value = call_inst.getArgOperand(1);
+  llvm::Value* object_addr = call_inst.getArgOperand(2);
+  uint32_t field_idx = LV2UInt(call_inst.getArgOperand(3));
+  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
+
+  EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
+
+  int field_offset;
+  bool is_volatile;
+  bool is_fast_path = driver_->ComputeInstanceFieldInfo(
+    field_idx, dex_compilation_unit_, field_offset, is_volatile, true);
+
+  if (!is_fast_path) {
+    llvm::Function* runtime_func;
+
+    if (field_jty == kFloat) {
+      new_value = irb_.CreateBitCast(new_value, irb_.getJType(kInt));
+    } else if (field_jty == kDouble) {
+      new_value = irb_.CreateBitCast(new_value, irb_.getJType(kLong));
+    }
+
+    if (field_jty == kObject) {
+      runtime_func = irb_.GetRuntime(runtime_support::SetObjectInstance);
+    } else if (field_jty == kLong || field_jty == kDouble) {
+      runtime_func = irb_.GetRuntime(runtime_support::Set64Instance);
+    } else {
+      runtime_func = irb_.GetRuntime(runtime_support::Set32Instance);
+    }
+
+    llvm::Value* field_idx_value = irb_.getInt32(field_idx);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    EmitUpdateDexPC(dex_pc);
+
+    irb_.CreateCall4(runtime_func, field_idx_value,
+                     method_object_addr, object_addr, new_value);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+  } else {
+    DCHECK_GE(field_offset, 0);
+
+    if (is_volatile) {
+      irb_.CreateMemoryBarrier(art::kStoreStore);
+    }
+
+    llvm::PointerType* field_type =
+      irb_.getJType(field_jty)->getPointerTo();
+
+    llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+    llvm::Value* field_addr =
+      irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
+
+    new_value = TruncateCat1Types(new_value, field_jty);
+    irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
+
+    if (is_volatile) {
+      irb_.CreateMemoryBarrier(art::kLoadLoad);
+    }
+
+    if (field_jty == kObject) { // If put an object, mark the GC card table.
+      EmitMarkGCCard(new_value, object_addr);
+    }
+  }
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::EmitLoadConstantClass(uint32_t dex_pc,
+                                                    uint32_t type_idx) {
+  if (!driver_->CanAccessTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
+                                           *dex_compilation_unit_->GetDexFile(), type_idx)) {
+    llvm::Value* type_idx_value = irb_.getInt32(type_idx);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
+
+    llvm::Function* runtime_func =
+      irb_.GetRuntime(runtime_support::InitializeTypeAndVerifyAccess);
+
+    EmitUpdateDexPC(dex_pc);
+
+    llvm::Value* type_object_addr =
+      irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+    return type_object_addr;
+
+  } else {
+    // Try to load the class (type) object from the test cache.
+    llvm::Value* type_field_addr =
+      EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
+
+    llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
+
+    if (driver_->CanAssumeTypeIsPresentInDexCache(*dex_compilation_unit_->GetDexFile(), type_idx)) {
+      return type_object_addr;
+    }
+
+    llvm::BasicBlock* block_original = irb_.GetInsertBlock();
+
+    // Test whether class (type) object is in the dex cache or not
+    llvm::Value* equal_null =
+      irb_.CreateICmpEQ(type_object_addr, irb_.getJNull());
+
+    llvm::BasicBlock* block_cont =
+      CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+    llvm::BasicBlock* block_load_class =
+      CreateBasicBlockWithDexPC(dex_pc, "load_class");
+
+    irb_.CreateCondBr(equal_null, block_load_class, block_cont, kUnlikely);
+
+    // Failback routine to load the class object
+    irb_.SetInsertPoint(block_load_class);
+
+    llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeType);
+
+    llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
+
+    EmitUpdateDexPC(dex_pc);
+
+    llvm::Value* loaded_type_object_addr =
+      irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+    llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
+
+    irb_.CreateBr(block_cont);
+
+    // Now the class object must be loaded
+    irb_.SetInsertPoint(block_cont);
+
+    llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
+
+    phi->addIncoming(type_object_addr, block_original);
+    phi->addIncoming(loaded_type_object_addr, block_after_load_class);
+
+    return phi;
+  }
+}
+
+llvm::Value* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc,
+                                                    uint32_t type_idx) {
+  llvm::BasicBlock* block_load_static =
+    CreateBasicBlockWithDexPC(dex_pc, "load_static");
+
+  llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+  // Load static storage from dex cache
+  llvm::Value* storage_field_addr =
+    EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
+
+  llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
+
+  llvm::BasicBlock* block_original = irb_.GetInsertBlock();
+
+  // Test: Is the static storage of this class initialized?
+  llvm::Value* equal_null =
+    irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
+
+  irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely);
+
+  // Failback routine to load the class object
+  irb_.SetInsertPoint(block_load_static);
+
+  llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeStaticStorage);
+
+  llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
+
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
+
+  EmitUpdateDexPC(dex_pc);
+
+  llvm::Value* loaded_storage_object_addr =
+    irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
+
+  EmitGuard_ExceptionLandingPad(dex_pc);
+
+  llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
+
+  irb_.CreateBr(block_cont);
+
+  // Now the class object must be loaded
+  irb_.SetInsertPoint(block_cont);
+
+  llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
+
+  phi->addIncoming(storage_object_addr, block_original);
+  phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
+
+  return phi;
+}
+
+llvm::Value* GBCExpanderPass::Expand_HLSget(llvm::CallInst& call_inst,
+                                            JType field_jty) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
+
+  int field_offset;
+  int ssb_index;
+  bool is_referrers_class;
+  bool is_volatile;
+
+  bool is_fast_path = driver_->ComputeStaticFieldInfo(
+    field_idx, dex_compilation_unit_, field_offset, ssb_index,
+    is_referrers_class, is_volatile, false);
+
+  llvm::Value* static_field_value;
+
+  if (!is_fast_path) {
+    llvm::Function* runtime_func;
+
+    if (field_jty == kObject) {
+      runtime_func = irb_.GetRuntime(runtime_support::GetObjectStatic);
+    } else if (field_jty == kLong || field_jty == kDouble) {
+      runtime_func = irb_.GetRuntime(runtime_support::Get64Static);
+    } else {
+      runtime_func = irb_.GetRuntime(runtime_support::Get32Static);
+    }
+
+    llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    EmitUpdateDexPC(dex_pc);
+
+    static_field_value =
+      irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+    if (field_jty == kFloat || field_jty == kDouble) {
+      static_field_value = irb_.CreateBitCast(static_field_value, irb_.getJType(field_jty));
+    }
+  } else {
+    DCHECK_GE(field_offset, 0);
+
+    llvm::Value* static_storage_addr = NULL;
+
+    if (is_referrers_class) {
+      // Fast path, static storage base is this method's class
+      llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+      static_storage_addr =
+        irb_.LoadFromObjectOffset(method_object_addr,
+                                  art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
+                                  irb_.getJObjectTy(),
+                                  kTBAAConstJObject);
+    } else {
+      // Medium path, static storage base in a different class which
+      // requires checks that the other class is initialized
+      DCHECK_GE(ssb_index, 0);
+      static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
+    }
+
+    llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+    llvm::Value* static_field_addr =
+      irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
+                         irb_.getJType(field_jty)->getPointerTo());
+
+    static_field_value = irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
+    static_field_value = SignOrZeroExtendCat1Types(static_field_value, field_jty);
+
+    if (is_volatile) {
+      irb_.CreateMemoryBarrier(art::kLoadLoad);
+    }
+  }
+
+  return static_field_value;
+}
+
+void GBCExpanderPass::Expand_HLSput(llvm::CallInst& call_inst,
+                                    JType field_jty) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
+  llvm::Value* new_value = call_inst.getArgOperand(1);
+
+  if (field_jty == kFloat || field_jty == kDouble) {
+    new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty));
+  }
+
+  int field_offset;
+  int ssb_index;
+  bool is_referrers_class;
+  bool is_volatile;
+
+  bool is_fast_path = driver_->ComputeStaticFieldInfo(
+    field_idx, dex_compilation_unit_, field_offset, ssb_index,
+    is_referrers_class, is_volatile, true);
+
+  if (!is_fast_path) {
+    llvm::Function* runtime_func;
+
+    if (field_jty == kObject) {
+      runtime_func = irb_.GetRuntime(runtime_support::SetObjectStatic);
+    } else if (field_jty == kLong || field_jty == kDouble) {
+      runtime_func = irb_.GetRuntime(runtime_support::Set64Static);
+    } else {
+      runtime_func = irb_.GetRuntime(runtime_support::Set32Static);
+    }
+
+    if (field_jty == kFloat) {
+      new_value = irb_.CreateBitCast(new_value, irb_.getJType(kInt));
+    } else if (field_jty == kDouble) {
+      new_value = irb_.CreateBitCast(new_value, irb_.getJType(kLong));
+    }
+
+    llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    EmitUpdateDexPC(dex_pc);
+
+    irb_.CreateCall3(runtime_func, field_idx_value,
+                     method_object_addr, new_value);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+  } else {
+    DCHECK_GE(field_offset, 0);
+
+    llvm::Value* static_storage_addr = NULL;
+
+    if (is_referrers_class) {
+      // Fast path, static storage base is this method's class
+      llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+      static_storage_addr =
+        irb_.LoadFromObjectOffset(method_object_addr,
+                                  art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
+                                  irb_.getJObjectTy(),
+                                  kTBAAConstJObject);
+    } else {
+      // Medium path, static storage base in a different class which
+      // requires checks that the other class is initialized
+      DCHECK_GE(ssb_index, 0);
+      static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
+    }
+
+    if (is_volatile) {
+      irb_.CreateMemoryBarrier(art::kStoreStore);
+    }
+
+    llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
+
+    llvm::Value* static_field_addr =
+      irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
+                         irb_.getJType(field_jty)->getPointerTo());
+
+    new_value = TruncateCat1Types(new_value, field_jty);
+    irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
+
+    if (is_volatile) {
+      irb_.CreateMemoryBarrier(art::kStoreLoad);
+    }
+
+    if (field_jty == kObject) { // If put an object, mark the GC card table.
+      EmitMarkGCCard(new_value, static_storage_addr);
+    }
+  }
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_ConstString(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t string_idx = LV2UInt(call_inst.getArgOperand(0));
+
+  llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
+
+  llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
+
+  if (!driver_->CanAssumeStringIsPresentInDexCache(*dex_compilation_unit_->GetDexFile(),
+                                                   string_idx)) {
+    llvm::BasicBlock* block_str_exist =
+      CreateBasicBlockWithDexPC(dex_pc, "str_exist");
+
+    llvm::BasicBlock* block_str_resolve =
+      CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
+
+    llvm::BasicBlock* block_cont =
+      CreateBasicBlockWithDexPC(dex_pc, "str_cont");
+
+    // Test: Is the string resolved and in the dex cache?
+    llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.getJNull());
+
+    irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist, kUnlikely);
+
+    // String is resolved, go to next basic block.
+    irb_.SetInsertPoint(block_str_exist);
+    irb_.CreateBr(block_cont);
+
+    // String is not resolved yet, resolve it now.
+    irb_.SetInsertPoint(block_str_resolve);
+
+    llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::ResolveString);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    llvm::Value* string_idx_value = irb_.getInt32(string_idx);
+
+    EmitUpdateDexPC(dex_pc);
+
+    llvm::Value* result = irb_.CreateCall2(runtime_func, method_object_addr,
+                                           string_idx_value);
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+
+    irb_.CreateBr(block_cont);
+
+
+    llvm::BasicBlock* block_pre_cont = irb_.GetInsertBlock();
+
+    irb_.SetInsertPoint(block_cont);
+
+    llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
+
+    phi->addIncoming(string_addr, block_str_exist);
+    phi->addIncoming(result, block_pre_cont);
+
+    string_addr = phi;
+  }
+
+  return string_addr;
+}
+
+llvm::Value* GBCExpanderPass::Expand_ConstClass(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
+
+  llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
+
+  return type_object_addr;
+}
+
+void GBCExpanderPass::Expand_MonitorEnter(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  llvm::Value* object_addr = call_inst.getArgOperand(1);
+  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
+
+  EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
+
+  EmitUpdateDexPC(dex_pc);
+
+  irb_.Runtime().EmitLockObject(object_addr);
+
+  return;
+}
+
+void GBCExpanderPass::Expand_MonitorExit(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  llvm::Value* object_addr = call_inst.getArgOperand(1);
+  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
+
+  EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
+
+  EmitUpdateDexPC(dex_pc);
+
+  irb_.Runtime().EmitUnlockObject(object_addr);
+
+  EmitGuard_ExceptionLandingPad(dex_pc);
+
+  return;
+}
+
+void GBCExpanderPass::Expand_HLCheckCast(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
+  llvm::Value* object_addr = call_inst.getArgOperand(1);
+
+  llvm::BasicBlock* block_test_class =
+    CreateBasicBlockWithDexPC(dex_pc, "test_class");
+
+  llvm::BasicBlock* block_test_sub_class =
+    CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
+
+  llvm::BasicBlock* block_cont =
+    CreateBasicBlockWithDexPC(dex_pc, "checkcast_cont");
+
+  // Test: Is the reference equal to null?  Act as no-op when it is null.
+  llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
+
+  irb_.CreateCondBr(equal_null, block_cont, block_test_class, kUnlikely);
+
+  // Test: Is the object instantiated from the given class?
+  irb_.SetInsertPoint(block_test_class);
+  llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
+  DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
+
+  llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
+
+  llvm::Value* object_type_field_addr =
+    irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
+
+  llvm::Value* object_type_object_addr =
+    irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
+
+  llvm::Value* equal_class =
+    irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
+
+  irb_.CreateCondBr(equal_class, block_cont, block_test_sub_class, kLikely);
+
+  // Test: Is the object instantiated from the subclass of the given class?
+  irb_.SetInsertPoint(block_test_sub_class);
+
+  EmitUpdateDexPC(dex_pc);
+
+  irb_.CreateCall2(irb_.GetRuntime(runtime_support::CheckCast),
+                   type_object_addr, object_type_object_addr);
+
+  EmitGuard_ExceptionLandingPad(dex_pc);
+
+  irb_.CreateBr(block_cont);
+
+  irb_.SetInsertPoint(block_cont);
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::Expand_InstanceOf(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
+  llvm::Value* object_addr = call_inst.getArgOperand(1);
+
+  llvm::BasicBlock* block_nullp =
+      CreateBasicBlockWithDexPC(dex_pc, "nullp");
+
+  llvm::BasicBlock* block_test_class =
+      CreateBasicBlockWithDexPC(dex_pc, "test_class");
+
+  llvm::BasicBlock* block_class_equals =
+      CreateBasicBlockWithDexPC(dex_pc, "class_eq");
+
+  llvm::BasicBlock* block_test_sub_class =
+      CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
+
+  llvm::BasicBlock* block_cont =
+      CreateBasicBlockWithDexPC(dex_pc, "instance_of_cont");
+
+  // Overview of the following code :
+  // We check for null, if so, then false, otherwise check for class == . If so
+  // then true, otherwise do callout slowpath.
+  //
+  // Test: Is the reference equal to null?  Set 0 when it is null.
+  llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
+
+  irb_.CreateCondBr(equal_null, block_nullp, block_test_class, kUnlikely);
+
+  irb_.SetInsertPoint(block_nullp);
+  irb_.CreateBr(block_cont);
+
+  // Test: Is the object instantiated from the given class?
+  irb_.SetInsertPoint(block_test_class);
+  llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
+  DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
+
+  llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
+
+  llvm::Value* object_type_field_addr =
+    irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
+
+  llvm::Value* object_type_object_addr =
+    irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
+
+  llvm::Value* equal_class =
+    irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
+
+  irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class, kLikely);
+
+  irb_.SetInsertPoint(block_class_equals);
+  irb_.CreateBr(block_cont);
+
+  // Test: Is the object instantiated from the subclass of the given class?
+  irb_.SetInsertPoint(block_test_sub_class);
+  llvm::Value* result =
+    irb_.CreateCall2(irb_.GetRuntime(runtime_support::IsAssignable),
+                     type_object_addr, object_type_object_addr);
+  irb_.CreateBr(block_cont);
+
+  irb_.SetInsertPoint(block_cont);
+
+  llvm::PHINode* phi = irb_.CreatePHI(irb_.getJIntTy(), 3);
+
+  phi->addIncoming(irb_.getJInt(0), block_nullp);
+  phi->addIncoming(irb_.getJInt(1), block_class_equals);
+  phi->addIncoming(result, block_test_sub_class);
+
+  return phi;
+}
+
+llvm::Value* GBCExpanderPass::Expand_NewInstance(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
+
+  llvm::Function* runtime_func;
+  if (driver_->CanAccessInstantiableTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
+                                                      *dex_compilation_unit_->GetDexFile(),
+                                                      type_idx)) {
+    runtime_func = irb_.GetRuntime(runtime_support::AllocObject);
+  } else {
+    runtime_func = irb_.GetRuntime(runtime_support::AllocObjectWithAccessCheck);
+  }
+
+  llvm::Constant* type_index_value = irb_.getInt32(type_idx);
+
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
+
+  EmitUpdateDexPC(dex_pc);
+
+  llvm::Value* object_addr =
+    irb_.CreateCall3(runtime_func, type_index_value, method_object_addr, thread_object_addr);
+
+  EmitGuard_ExceptionLandingPad(dex_pc);
+
+  return object_addr;
+}
+
+llvm::Value* GBCExpanderPass::Expand_HLInvoke(llvm::CallInst& call_inst) {
+  art::InvokeType invoke_type = static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
+  bool is_static = (invoke_type == art::kStatic);
+
+  if (!is_static) {
+    // Test: Is *this* parameter equal to null?
+    uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+    llvm::Value* this_addr = call_inst.getArgOperand(3);
+    int opt_flags = LV2UInt(call_inst.getArgOperand(2));
+
+    EmitGuard_NullPointerException(dex_pc, this_addr, opt_flags);
+  }
+
+  llvm::Value* result = NULL;
+  if (EmitIntrinsic(call_inst, &result)) {
+    return result;
+  }
+
+  return EmitInvoke(call_inst);
+}
+
+llvm::Value* GBCExpanderPass::Expand_OptArrayLength(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  // Get the array object address
+  llvm::Value* array_addr = call_inst.getArgOperand(1);
+  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
+
+  EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
+
+  // Get the array length and store it to the register
+  return EmitLoadArrayLength(array_addr);
+}
+
+llvm::Value* GBCExpanderPass::Expand_NewArray(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
+  llvm::Value* length = call_inst.getArgOperand(1);
+
+  return EmitAllocNewArray(dex_pc, length, type_idx, false);
+}
+
+llvm::Value* GBCExpanderPass::Expand_HLFilledNewArray(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(1));
+  uint32_t length = call_inst.getNumArgOperands() - 3;
+
+  llvm::Value* object_addr =
+    EmitAllocNewArray(dex_pc, irb_.getInt32(length), type_idx, true);
+
+  if (length > 0) {
+    // Check for the element type
+    uint32_t type_desc_len = 0;
+    const char* type_desc =
+        dex_compilation_unit_->GetDexFile()->StringByTypeIdx(type_idx, &type_desc_len);
+
+    DCHECK_GE(type_desc_len, 2u); // should be guaranteed by verifier
+    DCHECK_EQ(type_desc[0], '['); // should be guaranteed by verifier
+    bool is_elem_int_ty = (type_desc[1] == 'I');
+
+    uint32_t alignment;
+    llvm::Constant* elem_size;
+    llvm::PointerType* field_type;
+
+    // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
+    // as the element, thus we are only checking 2 cases: primitive int and
+    // non-primitive type.
+    if (is_elem_int_ty) {
+      alignment = sizeof(int32_t);
+      elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
+      field_type = irb_.getJIntTy()->getPointerTo();
+    } else {
+      alignment = irb_.getSizeOfPtrEquivInt();
+      elem_size = irb_.getSizeOfPtrEquivIntValue();
+      field_type = irb_.getJObjectTy()->getPointerTo();
+    }
+
+    llvm::Value* data_field_offset =
+      irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
+
+    llvm::Value* data_field_addr =
+      irb_.CreatePtrDisp(object_addr, data_field_offset, field_type);
+
+    // TODO: Tune this code.  Currently we are generating one instruction for
+    // one element which may be very space consuming.  Maybe changing to use
+    // memcpy may help; however, since we can't guarantee that the alloca of
+    // dalvik register are continuous, we can't perform such optimization yet.
+    for (uint32_t i = 0; i < length; ++i) {
+      llvm::Value* reg_value = call_inst.getArgOperand(i+3);
+
+      irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
+
+      data_field_addr =
+        irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
+    }
+  }
+
+  return object_addr;
+}
+
+void GBCExpanderPass::Expand_HLFillArrayData(llvm::CallInst& call_inst) {
+  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+  int32_t payload_offset = static_cast<int32_t>(dex_pc) +
+                           LV2SInt(call_inst.getArgOperand(0));
+  llvm::Value* array_addr = call_inst.getArgOperand(1);
+
+  const art::Instruction::ArrayDataPayload* payload =
+    reinterpret_cast<const art::Instruction::ArrayDataPayload*>(
+        dex_compilation_unit_->GetCodeItem()->insns_ + payload_offset);
+
+  if (payload->element_count == 0) {
+    // When the number of the elements in the payload is zero, we don't have
+    // to copy any numbers.  However, we should check whether the array object
+    // address is equal to null or not.
+    EmitGuard_NullPointerException(dex_pc, array_addr, 0);
+  } else {
+    // To save the code size, we are going to call the runtime function to
+    // copy the content from DexFile.
+
+    // NOTE: We will check for the NullPointerException in the runtime.
+
+    llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::FillArrayData);
+
+    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+    EmitUpdateDexPC(dex_pc);
+
+    irb_.CreateCall4(runtime_func,
+                     method_object_addr, irb_.getInt32(dex_pc),
+                     array_addr, irb_.getInt32(payload_offset));
+
+    EmitGuard_ExceptionLandingPad(dex_pc);
+  }
+
+  return;
+}
+
+llvm::Value* GBCExpanderPass::EmitAllocNewArray(uint32_t dex_pc,
+                                                llvm::Value* array_length_value,
+                                                uint32_t type_idx,
+                                                bool is_filled_new_array) {
+  llvm::Function* runtime_func;
+
+  bool skip_access_check =
+    driver_->CanAccessTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
+                                        *dex_compilation_unit_->GetDexFile(), type_idx);
+
+
+  if (is_filled_new_array) {
+    runtime_func = skip_access_check ?
+      irb_.GetRuntime(runtime_support::CheckAndAllocArray) :
+      irb_.GetRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck);
+  } else {
+    runtime_func = skip_access_check ?
+      irb_.GetRuntime(runtime_support::AllocArray) :
+      irb_.GetRuntime(runtime_support::AllocArrayWithAccessCheck);
+  }
+
+  llvm::Constant* type_index_value = irb_.getInt32(type_idx);
+
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
+
+  EmitUpdateDexPC(dex_pc);
+
+  llvm::Value* object_addr =
+    irb_.CreateCall4(runtime_func, type_index_value, method_object_addr,
+                     array_length_value, thread_object_addr);
+
+  EmitGuard_ExceptionLandingPad(dex_pc);
+
+  return object_addr;
+}
+
+llvm::Value* GBCExpanderPass::
+EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
+                                         art::InvokeType invoke_type,
+                                         llvm::Value* this_addr,
+                                         uint32_t dex_pc,
+                                         bool is_fast_path) {
+
+  llvm::Function* runtime_func = NULL;
+
+  switch (invoke_type) {
+  case art::kStatic:
+    runtime_func = irb_.GetRuntime(runtime_support::FindStaticMethodWithAccessCheck);
+    break;
+
+  case art::kDirect:
+    runtime_func = irb_.GetRuntime(runtime_support::FindDirectMethodWithAccessCheck);
+    break;
+
+  case art::kVirtual:
+    runtime_func = irb_.GetRuntime(runtime_support::FindVirtualMethodWithAccessCheck);
+    break;
+
+  case art::kSuper:
+    runtime_func = irb_.GetRuntime(runtime_support::FindSuperMethodWithAccessCheck);
+    break;
+
+  case art::kInterface:
+    if (is_fast_path) {
+      runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethod);
+    } else {
+      runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethodWithAccessCheck);
+    }
+    break;
+  }
+
+  llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
+
+  if (this_addr == NULL) {
+    DCHECK_EQ(invoke_type, art::kStatic);
+    this_addr = irb_.getJNull();
+  }
+
+  llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
+
+  llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
+
+  EmitUpdateDexPC(dex_pc);
+
+  llvm::Value* callee_method_object_addr =
+    irb_.CreateCall4(runtime_func,
+                     callee_method_idx_value,
+                     this_addr,
+                     caller_method_object_addr,
+                     thread_object_addr);
+
+  EmitGuard_ExceptionLandingPad(dex_pc);
+
+  return callee_method_object_addr;
+}
+
+void GBCExpanderPass::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
+  // Using runtime support, let the target can override by InlineAssembly.
+  irb_.Runtime().EmitMarkGCCard(value, target_addr);
+}
+
+void GBCExpanderPass::EmitUpdateDexPC(uint32_t dex_pc) {
+  if (shadow_frame_ == NULL) {
+    return;
+  }
+  irb_.StoreToObjectOffset(shadow_frame_,
+                           art::ShadowFrame::DexPCOffset(),
+                           irb_.getInt32(dex_pc),
+                           kTBAAShadowFrame);
+}
+
+void GBCExpanderPass::EmitGuard_DivZeroException(uint32_t dex_pc,
+                                                 llvm::Value* denominator,
+                                                 JType op_jty) {
+  DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
+
+  llvm::Constant* zero = irb_.getJZero(op_jty);
+
+  llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
+
+  llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
+
+  llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+  irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
+
+  irb_.SetInsertPoint(block_exception);
+  EmitUpdateDexPC(dex_pc);
+  irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowDivZeroException));
+  EmitBranchExceptionLandingPad(dex_pc);
+
+  irb_.SetInsertPoint(block_continue);
+}
+
+void GBCExpanderPass::EmitGuard_NullPointerException(uint32_t dex_pc,
+                                                     llvm::Value* object,
+                                                     int opt_flags) {
+  bool ignore_null_check = ((opt_flags & MIR_IGNORE_NULL_CHECK) != 0);
+  if (ignore_null_check) {
+    llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc);
+    if (lpad) {
+      // There is at least one catch: create a "fake" conditional branch to
+      // keep the exception edge to the catch block.
+      landing_pad_phi_mapping_[lpad].push_back(
+          std::make_pair(current_bb_->getUniquePredecessor(),
+                         irb_.GetInsertBlock()));
+
+      llvm::BasicBlock* block_continue =
+          CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+      irb_.CreateCondBr(irb_.getFalse(), lpad, block_continue, kUnlikely);
+
+      irb_.SetInsertPoint(block_continue);
+    }
+  } else {
+    llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
+
+    llvm::BasicBlock* block_exception =
+        CreateBasicBlockWithDexPC(dex_pc, "nullp");
+
+    llvm::BasicBlock* block_continue =
+        CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+    irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
+
+    irb_.SetInsertPoint(block_exception);
+    EmitUpdateDexPC(dex_pc);
+    irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowNullPointerException),
+                    irb_.getInt32(dex_pc));
+    EmitBranchExceptionLandingPad(dex_pc);
+
+    irb_.SetInsertPoint(block_continue);
+  }
+}
+
+void
+GBCExpanderPass::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
+                                                          llvm::Value* array,
+                                                          llvm::Value* index,
+                                                          int opt_flags) {
+  bool ignore_range_check = ((opt_flags & MIR_IGNORE_RANGE_CHECK) != 0);
+  if (ignore_range_check) {
+    llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc);
+    if (lpad) {
+      // There is at least one catch: create a "fake" conditional branch to
+      // keep the exception edge to the catch block.
+      landing_pad_phi_mapping_[lpad].push_back(
+          std::make_pair(current_bb_->getUniquePredecessor(),
+                         irb_.GetInsertBlock()));
+
+      llvm::BasicBlock* block_continue =
+          CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+      irb_.CreateCondBr(irb_.getFalse(), lpad, block_continue, kUnlikely);
+
+      irb_.SetInsertPoint(block_continue);
+    }
+  } else {
+    llvm::Value* array_len = EmitLoadArrayLength(array);
+
+    llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
+
+    llvm::BasicBlock* block_exception =
+        CreateBasicBlockWithDexPC(dex_pc, "overflow");
+
+    llvm::BasicBlock* block_continue =
+        CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+    irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
+
+    irb_.SetInsertPoint(block_exception);
+
+    EmitUpdateDexPC(dex_pc);
+    irb_.CreateCall2(irb_.GetRuntime(runtime_support::ThrowIndexOutOfBounds), index, array_len);
+    EmitBranchExceptionLandingPad(dex_pc);
+
+    irb_.SetInsertPoint(block_continue);
+  }
+}
+
+llvm::FunctionType* GBCExpanderPass::GetFunctionType(llvm::Type* ret_type, uint32_t method_idx,
+                                                     bool is_static) {
+  // Get method signature
+  art::DexFile::MethodId const& method_id =
+      dex_compilation_unit_->GetDexFile()->GetMethodId(method_idx);
+
+  uint32_t shorty_size;
+  const char* shorty = dex_compilation_unit_->GetDexFile()->GetMethodShorty(method_id, &shorty_size);
+  CHECK_GE(shorty_size, 1u);
+
+  // Get argument type
+  std::vector<llvm::Type*> args_type;
+
+  args_type.push_back(irb_.getJObjectTy()); // method object pointer
+
+  if (!is_static) {
+    args_type.push_back(irb_.getJType('L')); // "this" object pointer
+  }
+
+  for (uint32_t i = 1; i < shorty_size; ++i) {
+    char shorty_type = art::RemapShorty(shorty[i]);
+    args_type.push_back(irb_.getJType(shorty_type));
+  }
+
+  return llvm::FunctionType::get(ret_type, args_type, false);
+}
+
+
+llvm::BasicBlock* GBCExpanderPass::
+CreateBasicBlockWithDexPC(uint32_t dex_pc, const char* postfix) {
+  std::string name;
+
+#if !defined(NDEBUG)
+  art::StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
+#endif
+
+  return llvm::BasicBlock::Create(context_, name, func_);
+}
+
+llvm::BasicBlock* GBCExpanderPass::GetBasicBlock(uint32_t dex_pc) {
+  DCHECK(dex_pc < dex_compilation_unit_->GetCodeItem()->insns_size_in_code_units_);
+  CHECK(basic_blocks_[dex_pc] != NULL);
+  return basic_blocks_[dex_pc];
+}
+
+int32_t GBCExpanderPass::GetTryItemOffset(uint32_t dex_pc) {
+  int32_t min = 0;
+  int32_t max = dex_compilation_unit_->GetCodeItem()->tries_size_ - 1;
+
+  while (min <= max) {
+    int32_t mid = min + (max - min) / 2;
+
+    const art::DexFile::TryItem* ti =
+        art::DexFile::GetTryItems(*dex_compilation_unit_->GetCodeItem(), mid);
+    uint32_t start = ti->start_addr_;
+    uint32_t end = start + ti->insn_count_;
+
+    if (dex_pc < start) {
+      max = mid - 1;
+    } else if (dex_pc >= end) {
+      min = mid + 1;
+    } else {
+      return mid; // found
+    }
+  }
+
+  return -1; // not found
+}
+
+llvm::BasicBlock* GBCExpanderPass::GetLandingPadBasicBlock(uint32_t dex_pc) {
+  // Find the try item for this address in this method
+  int32_t ti_offset = GetTryItemOffset(dex_pc);
+
+  if (ti_offset == -1) {
+    return NULL; // No landing pad is available for this address.
+  }
+
+  // Check for the existing landing pad basic block
+  DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
+  llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
+
+  if (block_lpad) {
+    // We have generated landing pad for this try item already.  Return the
+    // same basic block.
+    return block_lpad;
+  }
+
+  // Get try item from code item
+  const art::DexFile::TryItem* ti = art::DexFile::GetTryItems(*dex_compilation_unit_->GetCodeItem(),
+                                                              ti_offset);
+
+  std::string lpadname;
+
+#if !defined(NDEBUG)
+  art::StringAppendF(&lpadname, "lpad%d_%04x_to_%04x", ti_offset, ti->start_addr_, ti->handler_off_);
+#endif
+
+  // Create landing pad basic block
+  block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
+
+  // Change IRBuilder insert point
+  llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
+  irb_.SetInsertPoint(block_lpad);
+
+  // Find catch block with matching type
+  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
+
+  llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
+
+  llvm::Value* catch_handler_index_value =
+    irb_.CreateCall2(irb_.GetRuntime(runtime_support::FindCatchBlock),
+                     method_object_addr, ti_offset_value);
+
+  // Switch instruction (Go to unwind basic block by default)
+  llvm::SwitchInst* sw =
+    irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
+
+  // Cases with matched catch block
+  art::CatchHandlerIterator iter(*dex_compilation_unit_->GetCodeItem(), ti->start_addr_);
+
+  for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
+    sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
+  }
+
+  // Restore the orignal insert point for IRBuilder
+  irb_.restoreIP(irb_ip_original);
+
+  // Cache this landing pad
+  DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
+  basic_block_landing_pads_[ti_offset] = block_lpad;
+
+  return block_lpad;
+}
+
+llvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() {
+  // Check the existing unwinding baisc block block
+  if (basic_block_unwind_ != NULL) {
+    return basic_block_unwind_;
+  }
+
+  // Create new basic block for unwinding
+  basic_block_unwind_ =
+    llvm::BasicBlock::Create(context_, "exception_unwind", func_);
+
+  // Change IRBuilder insert point
+  llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
+  irb_.SetInsertPoint(basic_block_unwind_);
+
+  // Pop the shadow frame
+  Expand_PopShadowFrame();
+
+  // Emit the code to return default value (zero) for the given return type.
+  char ret_shorty = dex_compilation_unit_->GetShorty()[0];
+  ret_shorty = art::RemapShorty(ret_shorty);
+  if (ret_shorty == 'V') {
+    irb_.CreateRetVoid();
+  } else {
+    irb_.CreateRet(irb_.getJZero(ret_shorty));
+  }
+
+  // Restore the orignal insert point for IRBuilder
+  irb_.restoreIP(irb_ip_original);
+
+  return basic_block_unwind_;
+}
+
+void GBCExpanderPass::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
+  if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
+    landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
+                                                            irb_.GetInsertBlock()));
+    irb_.CreateBr(lpad);
+  } else {
+    irb_.CreateBr(GetUnwindBasicBlock());
+  }
+}
+
+void GBCExpanderPass::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
+  llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
+
+  llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
+
+  if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
+    landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
+                                                            irb_.GetInsertBlock()));
+    irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
+  } else {
+    irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
+  }
+
+  irb_.SetInsertPoint(block_cont);
+}
+
+llvm::Value*
+GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
+                                 llvm::CallInst& call_inst) {
+  switch (intr_id) {
+    //==- Thread -----------------------------------------------------------==//
+    case IntrinsicHelper::GetCurrentThread: {
+      return irb_.Runtime().EmitGetCurrentThread();
+    }
+    case IntrinsicHelper::CheckSuspend: {
+      Expand_TestSuspend(call_inst);
+      return NULL;
+    }
+    case IntrinsicHelper::TestSuspend: {
+      Expand_TestSuspend(call_inst);
+      return NULL;
+    }
+    case IntrinsicHelper::MarkGCCard: {
+      Expand_MarkGCCard(call_inst);
+      return NULL;
+    }
+
+    //==- Exception --------------------------------------------------------==//
+    case IntrinsicHelper::ThrowException: {
+      return ExpandToRuntime(runtime_support::ThrowException, call_inst);
+    }
+    case IntrinsicHelper::HLThrowException: {
+      uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
+
+      EmitUpdateDexPC(dex_pc);
+
+      irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowException),
+                      call_inst.getArgOperand(0));
+
+      EmitGuard_ExceptionLandingPad(dex_pc);
+      return NULL;
+    }
+    case IntrinsicHelper::GetException: {
+      return irb_.Runtime().EmitGetAndClearException();
+    }
+    case IntrinsicHelper::IsExceptionPending: {
+      return irb_.Runtime().EmitIsExceptionPending();
+    }
+    case IntrinsicHelper::FindCatchBlock: {
+      return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
+    }
+    case IntrinsicHelper::ThrowDivZeroException: {
+      return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
+    }
+    case IntrinsicHelper::ThrowNullPointerException: {
+      return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
+    }
+    case IntrinsicHelper::ThrowIndexOutOfBounds: {
+      return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
+    }
+
+    //==- Const String -----------------------------------------------------==//
+    case IntrinsicHelper::ConstString: {
+      return Expand_ConstString(call_inst);
+    }
+    case IntrinsicHelper::LoadStringFromDexCache: {
+      return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::ResolveString: {
+      return ExpandToRuntime(runtime_support::ResolveString, call_inst);
+    }
+
+    //==- Const Class ------------------------------------------------------==//
+    case IntrinsicHelper::ConstClass: {
+      return Expand_ConstClass(call_inst);
+    }
+    case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
+      return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
+    }
+    case IntrinsicHelper::LoadTypeFromDexCache: {
+      return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::InitializeType: {
+      return ExpandToRuntime(runtime_support::InitializeType, call_inst);
+    }
+
+    //==- Lock -------------------------------------------------------------==//
+    case IntrinsicHelper::LockObject: {
+      Expand_LockObject(call_inst.getArgOperand(0));
+      return NULL;
+    }
+    case IntrinsicHelper::UnlockObject: {
+      Expand_UnlockObject(call_inst.getArgOperand(0));
+      return NULL;
+    }
+
+    //==- Cast -------------------------------------------------------------==//
+    case IntrinsicHelper::CheckCast: {
+      return ExpandToRuntime(runtime_support::CheckCast, call_inst);
+    }
+    case IntrinsicHelper::HLCheckCast: {
+      Expand_HLCheckCast(call_inst);
+      return NULL;
+    }
+    case IntrinsicHelper::IsAssignable: {
+      return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
+    }
+
+    //==- Alloc ------------------------------------------------------------==//
+    case IntrinsicHelper::AllocObject: {
+      return ExpandToRuntime(runtime_support::AllocObject, call_inst);
+    }
+    case IntrinsicHelper::AllocObjectWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
+    }
+
+    //==- Instance ---------------------------------------------------------==//
+    case IntrinsicHelper::NewInstance: {
+      return Expand_NewInstance(call_inst);
+    }
+    case IntrinsicHelper::InstanceOf: {
+      return Expand_InstanceOf(call_inst);
+    }
+
+    //==- Array ------------------------------------------------------------==//
+    case IntrinsicHelper::NewArray: {
+      return Expand_NewArray(call_inst);
+    }
+    case IntrinsicHelper::OptArrayLength: {
+      return Expand_OptArrayLength(call_inst);
+    }
+    case IntrinsicHelper::ArrayLength: {
+      return EmitLoadArrayLength(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::AllocArray: {
+      return ExpandToRuntime(runtime_support::AllocArray, call_inst);
+    }
+    case IntrinsicHelper::AllocArrayWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
+                             call_inst);
+    }
+    case IntrinsicHelper::CheckAndAllocArray: {
+      return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
+    }
+    case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
+                             call_inst);
+    }
+    case IntrinsicHelper::ArrayGet: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kInt);
+    }
+    case IntrinsicHelper::ArrayGetWide: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kLong);
+    }
+    case IntrinsicHelper::ArrayGetObject: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kObject);
+    }
+    case IntrinsicHelper::ArrayGetBoolean: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kBoolean);
+    }
+    case IntrinsicHelper::ArrayGetByte: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kByte);
+    }
+    case IntrinsicHelper::ArrayGetChar: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kChar);
+    }
+    case IntrinsicHelper::ArrayGetShort: {
+      return Expand_ArrayGet(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             kShort);
+    }
+    case IntrinsicHelper::ArrayPut: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kInt);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutWide: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kLong);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutObject: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kObject);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutBoolean: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kBoolean);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutByte: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kByte);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutChar: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kChar);
+      return NULL;
+    }
+    case IntrinsicHelper::ArrayPutShort: {
+      Expand_ArrayPut(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      kShort);
+      return NULL;
+    }
+    case IntrinsicHelper::CheckPutArrayElement: {
+      return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
+    }
+    case IntrinsicHelper::FilledNewArray: {
+      Expand_FilledNewArray(call_inst);
+      return NULL;
+    }
+    case IntrinsicHelper::FillArrayData: {
+      return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
+    }
+    case IntrinsicHelper::HLFillArrayData: {
+      Expand_HLFillArrayData(call_inst);
+      return NULL;
+    }
+    case IntrinsicHelper::HLFilledNewArray: {
+      return Expand_HLFilledNewArray(call_inst);
+    }
+
+    //==- Instance Field ---------------------------------------------------==//
+    case IntrinsicHelper::InstanceFieldGet:
+    case IntrinsicHelper::InstanceFieldGetBoolean:
+    case IntrinsicHelper::InstanceFieldGetByte:
+    case IntrinsicHelper::InstanceFieldGetChar:
+    case IntrinsicHelper::InstanceFieldGetShort: {
+      return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldGetWide: {
+      return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldGetObject: {
+      return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldGetFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kInt);
+    }
+    case IntrinsicHelper::InstanceFieldGetWideFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kLong);
+    }
+    case IntrinsicHelper::InstanceFieldGetObjectFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kObject);
+    }
+    case IntrinsicHelper::InstanceFieldGetBooleanFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kBoolean);
+    }
+    case IntrinsicHelper::InstanceFieldGetByteFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kByte);
+    }
+    case IntrinsicHelper::InstanceFieldGetCharFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kChar);
+    }
+    case IntrinsicHelper::InstanceFieldGetShortFast: {
+      return Expand_IGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kShort);
+    }
+    case IntrinsicHelper::InstanceFieldPut:
+    case IntrinsicHelper::InstanceFieldPutBoolean:
+    case IntrinsicHelper::InstanceFieldPutByte:
+    case IntrinsicHelper::InstanceFieldPutChar:
+    case IntrinsicHelper::InstanceFieldPutShort: {
+      return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldPutWide: {
+      return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldPutObject: {
+      return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
+    }
+    case IntrinsicHelper::InstanceFieldPutFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kInt);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutWideFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kLong);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutObjectFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kObject);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutBooleanFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kBoolean);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutByteFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kByte);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutCharFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kChar);
+      return NULL;
+    }
+    case IntrinsicHelper::InstanceFieldPutShortFast: {
+      Expand_IPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kShort);
+      return NULL;
+    }
+
+    //==- Static Field -----------------------------------------------------==//
+    case IntrinsicHelper::StaticFieldGet:
+    case IntrinsicHelper::StaticFieldGetBoolean:
+    case IntrinsicHelper::StaticFieldGetByte:
+    case IntrinsicHelper::StaticFieldGetChar:
+    case IntrinsicHelper::StaticFieldGetShort: {
+      return ExpandToRuntime(runtime_support::Get32Static, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldGetWide: {
+      return ExpandToRuntime(runtime_support::Get64Static, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldGetObject: {
+      return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldGetFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kInt);
+    }
+    case IntrinsicHelper::StaticFieldGetWideFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kLong);
+    }
+    case IntrinsicHelper::StaticFieldGetObjectFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kObject);
+    }
+    case IntrinsicHelper::StaticFieldGetBooleanFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kBoolean);
+    }
+    case IntrinsicHelper::StaticFieldGetByteFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kByte);
+    }
+    case IntrinsicHelper::StaticFieldGetCharFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kChar);
+    }
+    case IntrinsicHelper::StaticFieldGetShortFast: {
+      return Expand_SGetFast(call_inst.getArgOperand(0),
+                             call_inst.getArgOperand(1),
+                             call_inst.getArgOperand(2),
+                             kShort);
+    }
+    case IntrinsicHelper::StaticFieldPut:
+    case IntrinsicHelper::StaticFieldPutBoolean:
+    case IntrinsicHelper::StaticFieldPutByte:
+    case IntrinsicHelper::StaticFieldPutChar:
+    case IntrinsicHelper::StaticFieldPutShort: {
+      return ExpandToRuntime(runtime_support::Set32Static, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldPutWide: {
+      return ExpandToRuntime(runtime_support::Set64Static, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldPutObject: {
+      return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
+    }
+    case IntrinsicHelper::StaticFieldPutFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kInt);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutWideFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kLong);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutObjectFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kObject);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutBooleanFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kBoolean);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutByteFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kByte);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutCharFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kChar);
+      return NULL;
+    }
+    case IntrinsicHelper::StaticFieldPutShortFast: {
+      Expand_SPutFast(call_inst.getArgOperand(0),
+                      call_inst.getArgOperand(1),
+                      call_inst.getArgOperand(2),
+                      call_inst.getArgOperand(3),
+                      kShort);
+      return NULL;
+    }
+    case IntrinsicHelper::LoadDeclaringClassSSB: {
+      return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::LoadClassSSBFromDexCache: {
+      return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::InitializeAndLoadClassSSB: {
+      return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
+    }
+
+    //==- High-level Array -------------------------------------------------==//
+    case IntrinsicHelper::HLArrayGet: {
+      return Expand_HLArrayGet(call_inst, kInt);
+    }
+    case IntrinsicHelper::HLArrayGetBoolean: {
+      return Expand_HLArrayGet(call_inst, kBoolean);
+    }
+    case IntrinsicHelper::HLArrayGetByte: {
+      return Expand_HLArrayGet(call_inst, kByte);
+    }
+    case IntrinsicHelper::HLArrayGetChar: {
+      return Expand_HLArrayGet(call_inst, kChar);
+    }
+    case IntrinsicHelper::HLArrayGetShort: {
+      return Expand_HLArrayGet(call_inst, kShort);
+    }
+    case IntrinsicHelper::HLArrayGetFloat: {
+      return Expand_HLArrayGet(call_inst, kFloat);
+    }
+    case IntrinsicHelper::HLArrayGetWide: {
+      return Expand_HLArrayGet(call_inst, kLong);
+    }
+    case IntrinsicHelper::HLArrayGetDouble: {
+      return Expand_HLArrayGet(call_inst, kDouble);
+    }
+    case IntrinsicHelper::HLArrayGetObject: {
+      return Expand_HLArrayGet(call_inst, kObject);
+    }
+    case IntrinsicHelper::HLArrayPut: {
+      Expand_HLArrayPut(call_inst, kInt);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutBoolean: {
+      Expand_HLArrayPut(call_inst, kBoolean);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutByte: {
+      Expand_HLArrayPut(call_inst, kByte);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutChar: {
+      Expand_HLArrayPut(call_inst, kChar);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutShort: {
+      Expand_HLArrayPut(call_inst, kShort);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutFloat: {
+      Expand_HLArrayPut(call_inst, kFloat);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutWide: {
+      Expand_HLArrayPut(call_inst, kLong);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutDouble: {
+      Expand_HLArrayPut(call_inst, kDouble);
+      return NULL;
+    }
+    case IntrinsicHelper::HLArrayPutObject: {
+      Expand_HLArrayPut(call_inst, kObject);
+      return NULL;
+    }
+
+    //==- High-level Instance ----------------------------------------------==//
+    case IntrinsicHelper::HLIGet: {
+      return Expand_HLIGet(call_inst, kInt);
+    }
+    case IntrinsicHelper::HLIGetBoolean: {
+      return Expand_HLIGet(call_inst, kBoolean);
+    }
+    case IntrinsicHelper::HLIGetByte: {
+      return Expand_HLIGet(call_inst, kByte);
+    }
+    case IntrinsicHelper::HLIGetChar: {
+      return Expand_HLIGet(call_inst, kChar);
+    }
+    case IntrinsicHelper::HLIGetShort: {
+      return Expand_HLIGet(call_inst, kShort);
+    }
+    case IntrinsicHelper::HLIGetFloat: {
+      return Expand_HLIGet(call_inst, kFloat);
+    }
+    case IntrinsicHelper::HLIGetWide: {
+      return Expand_HLIGet(call_inst, kLong);
+    }
+    case IntrinsicHelper::HLIGetDouble: {
+      return Expand_HLIGet(call_inst, kDouble);
+    }
+    case IntrinsicHelper::HLIGetObject: {
+      return Expand_HLIGet(call_inst, kObject);
+    }
+    case IntrinsicHelper::HLIPut: {
+      Expand_HLIPut(call_inst, kInt);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutBoolean: {
+      Expand_HLIPut(call_inst, kBoolean);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutByte: {
+      Expand_HLIPut(call_inst, kByte);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutChar: {
+      Expand_HLIPut(call_inst, kChar);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutShort: {
+      Expand_HLIPut(call_inst, kShort);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutFloat: {
+      Expand_HLIPut(call_inst, kFloat);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutWide: {
+      Expand_HLIPut(call_inst, kLong);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutDouble: {
+      Expand_HLIPut(call_inst, kDouble);
+      return NULL;
+    }
+    case IntrinsicHelper::HLIPutObject: {
+      Expand_HLIPut(call_inst, kObject);
+      return NULL;
+    }
+
+    //==- High-level Invoke ------------------------------------------------==//
+    case IntrinsicHelper::HLInvokeVoid:
+    case IntrinsicHelper::HLInvokeObj:
+    case IntrinsicHelper::HLInvokeInt:
+    case IntrinsicHelper::HLInvokeFloat:
+    case IntrinsicHelper::HLInvokeLong:
+    case IntrinsicHelper::HLInvokeDouble: {
+      return Expand_HLInvoke(call_inst);
+    }
+
+    //==- Invoke -----------------------------------------------------------==//
+    case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
+    }
+    case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
+    }
+    case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
+    }
+    case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
+    }
+    case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
+      return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
+    }
+    case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
+      return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
+    }
+    case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
+      return Expand_GetVirtualCalleeMethodObjAddrFast(
+                call_inst.getArgOperand(0), call_inst.getArgOperand(1));
+    }
+    case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
+      return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
+    }
+    case IntrinsicHelper::InvokeRetVoid:
+    case IntrinsicHelper::InvokeRetBoolean:
+    case IntrinsicHelper::InvokeRetByte:
+    case IntrinsicHelper::InvokeRetChar:
+    case IntrinsicHelper::InvokeRetShort:
+    case IntrinsicHelper::InvokeRetInt:
+    case IntrinsicHelper::InvokeRetLong:
+    case IntrinsicHelper::InvokeRetFloat:
+    case IntrinsicHelper::InvokeRetDouble:
+    case IntrinsicHelper::InvokeRetObject: {
+      return Expand_Invoke(call_inst);
+    }
+
+    //==- Math -------------------------------------------------------------==//
+    case IntrinsicHelper::DivInt: {
+      return Expand_DivRem(call_inst, /* is_div */true, kInt);
+    }
+    case IntrinsicHelper::RemInt: {
+      return Expand_DivRem(call_inst, /* is_div */false, kInt);
+    }
+    case IntrinsicHelper::DivLong: {
+      return Expand_DivRem(call_inst, /* is_div */true, kLong);
+    }
+    case IntrinsicHelper::RemLong: {
+      return Expand_DivRem(call_inst, /* is_div */false, kLong);
+    }
+    case IntrinsicHelper::D2L: {
+      return ExpandToRuntime(runtime_support::art_d2l, call_inst);
+    }
+    case IntrinsicHelper::D2I: {
+      return ExpandToRuntime(runtime_support::art_d2i, call_inst);
+    }
+    case IntrinsicHelper::F2L: {
+      return ExpandToRuntime(runtime_support::art_f2l, call_inst);
+    }
+    case IntrinsicHelper::F2I: {
+      return ExpandToRuntime(runtime_support::art_f2i, call_inst);
+    }
+
+    //==- High-level Static ------------------------------------------------==//
+    case IntrinsicHelper::HLSget: {
+      return Expand_HLSget(call_inst, kInt);
+    }
+    case IntrinsicHelper::HLSgetBoolean: {
+      return Expand_HLSget(call_inst, kBoolean);
+    }
+    case IntrinsicHelper::HLSgetByte: {
+      return Expand_HLSget(call_inst, kByte);
+    }
+    case IntrinsicHelper::HLSgetChar: {
+      return Expand_HLSget(call_inst, kChar);
+    }
+    case IntrinsicHelper::HLSgetShort: {
+      return Expand_HLSget(call_inst, kShort);
+    }
+    case IntrinsicHelper::HLSgetFloat: {
+      return Expand_HLSget(call_inst, kFloat);
+    }
+    case IntrinsicHelper::HLSgetWide: {
+      return Expand_HLSget(call_inst, kLong);
+    }
+    case IntrinsicHelper::HLSgetDouble: {
+      return Expand_HLSget(call_inst, kDouble);
+    }
+    case IntrinsicHelper::HLSgetObject: {
+      return Expand_HLSget(call_inst, kObject);
+    }
+    case IntrinsicHelper::HLSput: {
+      Expand_HLSput(call_inst, kInt);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputBoolean: {
+      Expand_HLSput(call_inst, kBoolean);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputByte: {
+      Expand_HLSput(call_inst, kByte);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputChar: {
+      Expand_HLSput(call_inst, kChar);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputShort: {
+      Expand_HLSput(call_inst, kShort);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputFloat: {
+      Expand_HLSput(call_inst, kFloat);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputWide: {
+      Expand_HLSput(call_inst, kLong);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputDouble: {
+      Expand_HLSput(call_inst, kDouble);
+      return NULL;
+    }
+    case IntrinsicHelper::HLSputObject: {
+      Expand_HLSput(call_inst, kObject);
+      return NULL;
+    }
+
+    //==- High-level Monitor -----------------------------------------------==//
+    case IntrinsicHelper::MonitorEnter: {
+      Expand_MonitorEnter(call_inst);
+      return NULL;
+    }
+    case IntrinsicHelper::MonitorExit: {
+      Expand_MonitorExit(call_inst);
+      return NULL;
+    }
+
+    //==- Shadow Frame -----------------------------------------------------==//
+    case IntrinsicHelper::AllocaShadowFrame: {
+      Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
+      return NULL;
+    }
+    case IntrinsicHelper::SetVReg: {
+      Expand_SetVReg(call_inst.getArgOperand(0),
+                     call_inst.getArgOperand(1));
+      return NULL;
+    }
+    case IntrinsicHelper::PopShadowFrame: {
+      Expand_PopShadowFrame();
+      return NULL;
+    }
+    case IntrinsicHelper::UpdateDexPC: {
+      Expand_UpdateDexPC(call_inst.getArgOperand(0));
+      return NULL;
+    }
+
+    //==- Comparison -------------------------------------------------------==//
+    case IntrinsicHelper::CmplFloat:
+    case IntrinsicHelper::CmplDouble: {
+      return Expand_FPCompare(call_inst.getArgOperand(0),
+                              call_inst.getArgOperand(1),
+                              false);
+    }
+    case IntrinsicHelper::CmpgFloat:
+    case IntrinsicHelper::CmpgDouble: {
+      return Expand_FPCompare(call_inst.getArgOperand(0),
+                              call_inst.getArgOperand(1),
+                              true);
+    }
+    case IntrinsicHelper::CmpLong: {
+      return Expand_LongCompare(call_inst.getArgOperand(0),
+                                call_inst.getArgOperand(1));
+    }
+
+    //==- Const ------------------------------------------------------------==//
+    case IntrinsicHelper::ConstInt:
+    case IntrinsicHelper::ConstLong: {
+      return call_inst.getArgOperand(0);
+    }
+    case IntrinsicHelper::ConstFloat: {
+      return irb_.CreateBitCast(call_inst.getArgOperand(0),
+                                irb_.getJFloatTy());
+    }
+    case IntrinsicHelper::ConstDouble: {
+      return irb_.CreateBitCast(call_inst.getArgOperand(0),
+                                irb_.getJDoubleTy());
+    }
+    case IntrinsicHelper::ConstObj: {
+      CHECK(LV2UInt(call_inst.getArgOperand(0)) == 0);
+      return irb_.getJNull();
+    }
+
+    //==- Method Info ------------------------------------------------------==//
+    case IntrinsicHelper::MethodInfo: {
+      // Nothing to be done, because MethodInfo carries optional hints that are
+      // not needed by the portable path.
+      return NULL;
+    }
+
+    //==- Copy -------------------------------------------------------------==//
+    case IntrinsicHelper::CopyInt:
+    case IntrinsicHelper::CopyFloat:
+    case IntrinsicHelper::CopyLong:
+    case IntrinsicHelper::CopyDouble:
+    case IntrinsicHelper::CopyObj: {
+      return call_inst.getArgOperand(0);
+    }
+
+    //==- Shift ------------------------------------------------------------==//
+    case IntrinsicHelper::SHLLong: {
+      return Expand_IntegerShift(call_inst.getArgOperand(0),
+                                 call_inst.getArgOperand(1),
+                                 kIntegerSHL, kLong);
+    }
+    case IntrinsicHelper::SHRLong: {
+      return Expand_IntegerShift(call_inst.getArgOperand(0),
+                                 call_inst.getArgOperand(1),
+                                 kIntegerSHR, kLong);
+    }
+    case IntrinsicHelper::USHRLong: {
+      return Expand_IntegerShift(call_inst.getArgOperand(0),
+                                 call_inst.getArgOperand(1),
+                                 kIntegerUSHR, kLong);
+    }
+    case IntrinsicHelper::SHLInt: {
+      return Expand_IntegerShift(call_inst.getArgOperand(0),
+                                 call_inst.getArgOperand(1),
+                                 kIntegerSHL, kInt);
+    }
+    case IntrinsicHelper::SHRInt: {
+      return Expand_IntegerShift(call_inst.getArgOperand(0),
+                                 call_inst.getArgOperand(1),
+                                 kIntegerSHR, kInt);
+    }
+    case IntrinsicHelper::USHRInt: {
+      return Expand_IntegerShift(call_inst.getArgOperand(0),
+                                 call_inst.getArgOperand(1),
+                                 kIntegerUSHR, kInt);
+    }
+
+    //==- Conversion -------------------------------------------------------==//
+    case IntrinsicHelper::IntToChar: {
+      return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
+                             irb_.getJIntTy());
+    }
+    case IntrinsicHelper::IntToShort: {
+      return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
+                             irb_.getJIntTy());
+    }
+    case IntrinsicHelper::IntToByte: {
+      return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
+                             irb_.getJIntTy());
+    }
+
+    //==- Exception --------------------------------------------------------==//
+    case IntrinsicHelper::CatchTargets: {
+      UpdatePhiInstruction(current_bb_, irb_.GetInsertBlock());
+      llvm::SwitchInst* si = llvm::dyn_cast<llvm::SwitchInst>(call_inst.getNextNode());
+      CHECK(si != NULL);
+      irb_.CreateBr(si->getDefaultDest());
+      si->eraseFromParent();
+      return call_inst.getArgOperand(0);
+    }
+
+    //==- Constructor barrier-----------------------------------------------==//
+    case IntrinsicHelper::ConstructorBarrier: {
+      irb_.CreateMemoryBarrier(art::kStoreStore);
+      return NULL;
+    }
+
+    //==- Unknown Cases ----------------------------------------------------==//
+    case IntrinsicHelper::MaxIntrinsicId:
+    case IntrinsicHelper::UnknownId:
+    //default:
+      // NOTE: "default" is intentionally commented so that C/C++ compiler will
+      // give some warning on unmatched cases.
+      // NOTE: We should not implement these cases.
+      break;
+  }
+  UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
+  return NULL;
+}
+
+} // anonymous namespace
+
+namespace art {
+namespace llvm {
+
+::llvm::FunctionPass*
+CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
+                      CompilerDriver* driver, const DexCompilationUnit* dex_compilation_unit) {
+  return new GBCExpanderPass(intrinsic_helper, irb, driver, dex_compilation_unit);
+}
+
+} // namespace llvm
+} // namespace art
diff --git a/compiler/llvm/generated/art_module.cc b/compiler/llvm/generated/art_module.cc
new file mode 100644
index 0000000..bcd90b9
--- /dev/null
+++ b/compiler/llvm/generated/art_module.cc
@@ -0,0 +1,1096 @@
+// Generated with ./gen_art_module_cc.sh
+
+
+#pragma GCC diagnostic ignored "-Wframe-larger-than="
+// TODO: Remove this pragma after llc can generate makeLLVMModuleContents()
+// with smaller frame size.
+
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+
+#include <vector>
+
+using namespace llvm;
+
+namespace art {
+namespace llvm {
+
+
+// Generated by llvm2cpp - DO NOT MODIFY!
+
+
+Module* makeLLVMModuleContents(Module *mod) {
+
+mod->setModuleIdentifier("art_module.ll");
+
+// Type Definitions
+std::vector<Type*>FuncTy_0_args;
+StructType *StructTy_JavaObject = mod->getTypeByName("JavaObject");
+if (!StructTy_JavaObject) {
+StructTy_JavaObject = StructType::create(mod->getContext(), "JavaObject");
+}
+std::vector<Type*>StructTy_JavaObject_fields;
+if (StructTy_JavaObject->isOpaque()) {
+StructTy_JavaObject->setBody(StructTy_JavaObject_fields, /*isPacked=*/false);
+}
+
+PointerType* PointerTy_1 = PointerType::get(StructTy_JavaObject, 0);
+
+FuncTy_0_args.push_back(PointerTy_1);
+StructType *StructTy_ShadowFrame = mod->getTypeByName("ShadowFrame");
+if (!StructTy_ShadowFrame) {
+StructTy_ShadowFrame = StructType::create(mod->getContext(), "ShadowFrame");
+}
+std::vector<Type*>StructTy_ShadowFrame_fields;
+StructTy_ShadowFrame_fields.push_back(IntegerType::get(mod->getContext(), 32));
+PointerType* PointerTy_2 = PointerType::get(StructTy_ShadowFrame, 0);
+
+StructTy_ShadowFrame_fields.push_back(PointerTy_2);
+StructTy_ShadowFrame_fields.push_back(PointerTy_1);
+StructTy_ShadowFrame_fields.push_back(IntegerType::get(mod->getContext(), 32));
+if (StructTy_ShadowFrame->isOpaque()) {
+StructTy_ShadowFrame->setBody(StructTy_ShadowFrame_fields, /*isPacked=*/false);
+}
+
+
+FuncTy_0_args.push_back(PointerTy_2);
+FunctionType* FuncTy_0 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Params=*/FuncTy_0_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_3_args;
+FunctionType* FuncTy_3 = FunctionType::get(
+ /*Result=*/PointerTy_1,
+ /*Params=*/FuncTy_3_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_4_args;
+FuncTy_4_args.push_back(PointerTy_1);
+FunctionType* FuncTy_4 = FunctionType::get(
+ /*Result=*/PointerTy_1,
+ /*Params=*/FuncTy_4_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_5_args;
+FuncTy_5_args.push_back(PointerTy_1);
+FuncTy_5_args.push_back(PointerTy_1);
+FunctionType* FuncTy_5 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Params=*/FuncTy_5_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_6_args;
+FuncTy_6_args.push_back(PointerTy_1);
+FunctionType* FuncTy_6 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Params=*/FuncTy_6_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_7_args;
+FuncTy_7_args.push_back(PointerTy_1);
+FuncTy_7_args.push_back(PointerTy_2);
+FuncTy_7_args.push_back(PointerTy_1);
+FuncTy_7_args.push_back(IntegerType::get(mod->getContext(), 32));
+FunctionType* FuncTy_7 = FunctionType::get(
+ /*Result=*/PointerTy_2,
+ /*Params=*/FuncTy_7_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_8_args;
+FuncTy_8_args.push_back(PointerTy_2);
+FunctionType* FuncTy_8 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Params=*/FuncTy_8_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_9_args;
+FunctionType* FuncTy_9 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Params=*/FuncTy_9_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_10_args;
+FuncTy_10_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_10_args.push_back(IntegerType::get(mod->getContext(), 32));
+FunctionType* FuncTy_10 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Params=*/FuncTy_10_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_11_args;
+FuncTy_11_args.push_back(IntegerType::get(mod->getContext(), 32));
+FunctionType* FuncTy_11 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Params=*/FuncTy_11_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_12_args;
+FuncTy_12_args.push_back(PointerTy_1);
+FuncTy_12_args.push_back(IntegerType::get(mod->getContext(), 32));
+FunctionType* FuncTy_12 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Params=*/FuncTy_12_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_13_args;
+FuncTy_13_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_13_args.push_back(PointerTy_1);
+FuncTy_13_args.push_back(PointerTy_1);
+FunctionType* FuncTy_13 = FunctionType::get(
+ /*Result=*/PointerTy_1,
+ /*Params=*/FuncTy_13_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_14_args;
+FuncTy_14_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_14_args.push_back(PointerTy_1);
+FuncTy_14_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_14_args.push_back(PointerTy_1);
+FunctionType* FuncTy_14 = FunctionType::get(
+ /*Result=*/PointerTy_1,
+ /*Params=*/FuncTy_14_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_15_args;
+FuncTy_15_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_15_args.push_back(PointerTy_1);
+FunctionType* FuncTy_15 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Params=*/FuncTy_15_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_16_args;
+FuncTy_16_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_16_args.push_back(PointerTy_1);
+FuncTy_16_args.push_back(PointerTy_1);
+FuncTy_16_args.push_back(PointerTy_1);
+FunctionType* FuncTy_16 = FunctionType::get(
+ /*Result=*/PointerTy_1,
+ /*Params=*/FuncTy_16_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_17_args;
+FuncTy_17_args.push_back(PointerTy_1);
+FuncTy_17_args.push_back(IntegerType::get(mod->getContext(), 32));
+FunctionType* FuncTy_17 = FunctionType::get(
+ /*Result=*/PointerTy_1,
+ /*Params=*/FuncTy_17_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_18_args;
+FuncTy_18_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_18_args.push_back(PointerTy_1);
+FuncTy_18_args.push_back(IntegerType::get(mod->getContext(), 32));
+FunctionType* FuncTy_18 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Params=*/FuncTy_18_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_19_args;
+FuncTy_19_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_19_args.push_back(PointerTy_1);
+FuncTy_19_args.push_back(IntegerType::get(mod->getContext(), 64));
+FunctionType* FuncTy_19 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Params=*/FuncTy_19_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_20_args;
+FuncTy_20_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_20_args.push_back(PointerTy_1);
+FuncTy_20_args.push_back(PointerTy_1);
+FunctionType* FuncTy_20 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Params=*/FuncTy_20_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_21_args;
+FuncTy_21_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_21_args.push_back(PointerTy_1);
+FunctionType* FuncTy_21 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Params=*/FuncTy_21_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_22_args;
+FuncTy_22_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_22_args.push_back(PointerTy_1);
+FunctionType* FuncTy_22 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 64),
+ /*Params=*/FuncTy_22_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_23_args;
+FuncTy_23_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_23_args.push_back(PointerTy_1);
+FunctionType* FuncTy_23 = FunctionType::get(
+ /*Result=*/PointerTy_1,
+ /*Params=*/FuncTy_23_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_24_args;
+FuncTy_24_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_24_args.push_back(PointerTy_1);
+FuncTy_24_args.push_back(PointerTy_1);
+FuncTy_24_args.push_back(IntegerType::get(mod->getContext(), 32));
+FunctionType* FuncTy_24 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Params=*/FuncTy_24_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_25_args;
+FuncTy_25_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_25_args.push_back(PointerTy_1);
+FuncTy_25_args.push_back(PointerTy_1);
+FuncTy_25_args.push_back(IntegerType::get(mod->getContext(), 64));
+FunctionType* FuncTy_25 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Params=*/FuncTy_25_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_26_args;
+FuncTy_26_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_26_args.push_back(PointerTy_1);
+FuncTy_26_args.push_back(PointerTy_1);
+FuncTy_26_args.push_back(PointerTy_1);
+FunctionType* FuncTy_26 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Params=*/FuncTy_26_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_27_args;
+FuncTy_27_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_27_args.push_back(PointerTy_1);
+FuncTy_27_args.push_back(PointerTy_1);
+FunctionType* FuncTy_27 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 64),
+ /*Params=*/FuncTy_27_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_28_args;
+FuncTy_28_args.push_back(PointerTy_1);
+FuncTy_28_args.push_back(PointerTy_1);
+FunctionType* FuncTy_28 = FunctionType::get(
+ /*Result=*/PointerTy_1,
+ /*Params=*/FuncTy_28_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_29_args;
+FuncTy_29_args.push_back(PointerTy_1);
+FuncTy_29_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_29_args.push_back(PointerTy_1);
+FuncTy_29_args.push_back(IntegerType::get(mod->getContext(), 32));
+FunctionType* FuncTy_29 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Params=*/FuncTy_29_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_30_args;
+FuncTy_30_args.push_back(PointerTy_1);
+FuncTy_30_args.push_back(PointerTy_1);
+FunctionType* FuncTy_30 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Params=*/FuncTy_30_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_31_args;
+FuncTy_31_args.push_back(Type::getDoubleTy(mod->getContext()));
+FunctionType* FuncTy_31 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 64),
+ /*Params=*/FuncTy_31_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_32_args;
+FuncTy_32_args.push_back(Type::getDoubleTy(mod->getContext()));
+FunctionType* FuncTy_32 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Params=*/FuncTy_32_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_33_args;
+FuncTy_33_args.push_back(Type::getFloatTy(mod->getContext()));
+FunctionType* FuncTy_33 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 64),
+ /*Params=*/FuncTy_33_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_34_args;
+FuncTy_34_args.push_back(Type::getFloatTy(mod->getContext()));
+FunctionType* FuncTy_34 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Params=*/FuncTy_34_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_35_args;
+FuncTy_35_args.push_back(PointerTy_1);
+FunctionType* FuncTy_35 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 32),
+ /*Params=*/FuncTy_35_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_36_args;
+FuncTy_36_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_36_args.push_back(PointerTy_1);
+FuncTy_36_args.push_back(PointerTy_1);
+FunctionType* FuncTy_36 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Params=*/FuncTy_36_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_37_args;
+FuncTy_37_args.push_back(PointerTy_1);
+FuncTy_37_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_37_args.push_back(PointerTy_1);
+FunctionType* FuncTy_37 = FunctionType::get(
+ /*Result=*/PointerTy_1,
+ /*Params=*/FuncTy_37_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_38_args;
+FuncTy_38_args.push_back(PointerTy_1);
+FuncTy_38_args.push_back(IntegerType::get(mod->getContext(), 32));
+FuncTy_38_args.push_back(PointerTy_1);
+FuncTy_38_args.push_back(PointerTy_1);
+FunctionType* FuncTy_38 = FunctionType::get(
+ /*Result=*/PointerTy_1,
+ /*Params=*/FuncTy_38_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_39_args;
+FunctionType* FuncTy_39 = FunctionType::get(
+ /*Result=*/IntegerType::get(mod->getContext(), 1),
+ /*Params=*/FuncTy_39_args,
+ /*isVarArg=*/false);
+
+std::vector<Type*>FuncTy_40_args;
+FuncTy_40_args.push_back(PointerTy_1);
+FunctionType* FuncTy_40 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(mod->getContext()),
+ /*Params=*/FuncTy_40_args,
+ /*isVarArg=*/true);
+
+
+// Function Declarations
+
+Function* func___art_type_list = mod->getFunction("__art_type_list");
+if (!func___art_type_list) {
+func___art_type_list = Function::Create(
+ /*Type=*/FuncTy_0,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"__art_type_list", mod); // (external, no body)
+func___art_type_list->setCallingConv(CallingConv::C);
+}
+AttributeSet func___art_type_list_PAL;
+func___art_type_list->setAttributes(func___art_type_list_PAL);
+
+Function* func_art_portable_get_current_thread_from_code = mod->getFunction("art_portable_get_current_thread_from_code");
+if (!func_art_portable_get_current_thread_from_code) {
+func_art_portable_get_current_thread_from_code = Function::Create(
+ /*Type=*/FuncTy_3,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_get_current_thread_from_code", mod); // (external, no body)
+func_art_portable_get_current_thread_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_get_current_thread_from_code_PAL;
+func_art_portable_get_current_thread_from_code->setAttributes(func_art_portable_get_current_thread_from_code_PAL);
+
+Function* func_art_portable_set_current_thread_from_code = mod->getFunction("art_portable_set_current_thread_from_code");
+if (!func_art_portable_set_current_thread_from_code) {
+func_art_portable_set_current_thread_from_code = Function::Create(
+ /*Type=*/FuncTy_4,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_set_current_thread_from_code", mod); // (external, no body)
+func_art_portable_set_current_thread_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_set_current_thread_from_code_PAL;
+func_art_portable_set_current_thread_from_code->setAttributes(func_art_portable_set_current_thread_from_code_PAL);
+
+Function* func_art_portable_lock_object_from_code = mod->getFunction("art_portable_lock_object_from_code");
+if (!func_art_portable_lock_object_from_code) {
+func_art_portable_lock_object_from_code = Function::Create(
+ /*Type=*/FuncTy_5,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_lock_object_from_code", mod); // (external, no body)
+func_art_portable_lock_object_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_lock_object_from_code_PAL;
+func_art_portable_lock_object_from_code->setAttributes(func_art_portable_lock_object_from_code_PAL);
+
+Function* func_art_portable_unlock_object_from_code = mod->getFunction("art_portable_unlock_object_from_code");
+if (!func_art_portable_unlock_object_from_code) {
+func_art_portable_unlock_object_from_code = Function::Create(
+ /*Type=*/FuncTy_5,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_unlock_object_from_code", mod); // (external, no body)
+func_art_portable_unlock_object_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_unlock_object_from_code_PAL;
+func_art_portable_unlock_object_from_code->setAttributes(func_art_portable_unlock_object_from_code_PAL);
+
+Function* func_art_portable_test_suspend_from_code = mod->getFunction("art_portable_test_suspend_from_code");
+if (!func_art_portable_test_suspend_from_code) {
+func_art_portable_test_suspend_from_code = Function::Create(
+ /*Type=*/FuncTy_6,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_test_suspend_from_code", mod); // (external, no body)
+func_art_portable_test_suspend_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_test_suspend_from_code_PAL;
+func_art_portable_test_suspend_from_code->setAttributes(func_art_portable_test_suspend_from_code_PAL);
+
+Function* func_art_portable_push_shadow_frame_from_code = mod->getFunction("art_portable_push_shadow_frame_from_code");
+if (!func_art_portable_push_shadow_frame_from_code) {
+func_art_portable_push_shadow_frame_from_code = Function::Create(
+ /*Type=*/FuncTy_7,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_push_shadow_frame_from_code", mod); // (external, no body)
+func_art_portable_push_shadow_frame_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_push_shadow_frame_from_code_PAL;
+func_art_portable_push_shadow_frame_from_code->setAttributes(func_art_portable_push_shadow_frame_from_code_PAL);
+
+Function* func_art_portable_pop_shadow_frame_from_code = mod->getFunction("art_portable_pop_shadow_frame_from_code");
+if (!func_art_portable_pop_shadow_frame_from_code) {
+func_art_portable_pop_shadow_frame_from_code = Function::Create(
+ /*Type=*/FuncTy_8,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_pop_shadow_frame_from_code", mod); // (external, no body)
+func_art_portable_pop_shadow_frame_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_pop_shadow_frame_from_code_PAL;
+func_art_portable_pop_shadow_frame_from_code->setAttributes(func_art_portable_pop_shadow_frame_from_code_PAL);
+
+Function* func_art_portable_get_and_clear_exception = mod->getFunction("art_portable_get_and_clear_exception");
+if (!func_art_portable_get_and_clear_exception) {
+func_art_portable_get_and_clear_exception = Function::Create(
+ /*Type=*/FuncTy_4,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_get_and_clear_exception", mod); // (external, no body)
+func_art_portable_get_and_clear_exception->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_get_and_clear_exception_PAL;
+func_art_portable_get_and_clear_exception->setAttributes(func_art_portable_get_and_clear_exception_PAL);
+
+Function* func_art_portable_throw_div_zero_from_code = mod->getFunction("art_portable_throw_div_zero_from_code");
+if (!func_art_portable_throw_div_zero_from_code) {
+func_art_portable_throw_div_zero_from_code = Function::Create(
+ /*Type=*/FuncTy_9,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_throw_div_zero_from_code", mod); // (external, no body)
+func_art_portable_throw_div_zero_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_throw_div_zero_from_code_PAL;
+func_art_portable_throw_div_zero_from_code->setAttributes(func_art_portable_throw_div_zero_from_code_PAL);
+
+Function* func_art_portable_throw_array_bounds_from_code = mod->getFunction("art_portable_throw_array_bounds_from_code");
+if (!func_art_portable_throw_array_bounds_from_code) {
+func_art_portable_throw_array_bounds_from_code = Function::Create(
+ /*Type=*/FuncTy_10,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_throw_array_bounds_from_code", mod); // (external, no body)
+func_art_portable_throw_array_bounds_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_throw_array_bounds_from_code_PAL;
+func_art_portable_throw_array_bounds_from_code->setAttributes(func_art_portable_throw_array_bounds_from_code_PAL);
+
+Function* func_art_portable_throw_no_such_method_from_code = mod->getFunction("art_portable_throw_no_such_method_from_code");
+if (!func_art_portable_throw_no_such_method_from_code) {
+func_art_portable_throw_no_such_method_from_code = Function::Create(
+ /*Type=*/FuncTy_11,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_throw_no_such_method_from_code", mod); // (external, no body)
+func_art_portable_throw_no_such_method_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_throw_no_such_method_from_code_PAL;
+func_art_portable_throw_no_such_method_from_code->setAttributes(func_art_portable_throw_no_such_method_from_code_PAL);
+
+Function* func_art_portable_throw_null_pointer_exception_from_code = mod->getFunction("art_portable_throw_null_pointer_exception_from_code");
+if (!func_art_portable_throw_null_pointer_exception_from_code) {
+func_art_portable_throw_null_pointer_exception_from_code = Function::Create(
+ /*Type=*/FuncTy_11,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_throw_null_pointer_exception_from_code", mod); // (external, no body)
+func_art_portable_throw_null_pointer_exception_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_throw_null_pointer_exception_from_code_PAL;
+func_art_portable_throw_null_pointer_exception_from_code->setAttributes(func_art_portable_throw_null_pointer_exception_from_code_PAL);
+
+Function* func_art_portable_throw_stack_overflow_from_code = mod->getFunction("art_portable_throw_stack_overflow_from_code");
+if (!func_art_portable_throw_stack_overflow_from_code) {
+func_art_portable_throw_stack_overflow_from_code = Function::Create(
+ /*Type=*/FuncTy_9,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_throw_stack_overflow_from_code", mod); // (external, no body)
+func_art_portable_throw_stack_overflow_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_throw_stack_overflow_from_code_PAL;
+func_art_portable_throw_stack_overflow_from_code->setAttributes(func_art_portable_throw_stack_overflow_from_code_PAL);
+
+Function* func_art_portable_throw_exception_from_code = mod->getFunction("art_portable_throw_exception_from_code");
+if (!func_art_portable_throw_exception_from_code) {
+func_art_portable_throw_exception_from_code = Function::Create(
+ /*Type=*/FuncTy_6,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_throw_exception_from_code", mod); // (external, no body)
+func_art_portable_throw_exception_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_throw_exception_from_code_PAL;
+func_art_portable_throw_exception_from_code->setAttributes(func_art_portable_throw_exception_from_code_PAL);
+
+Function* func_art_portable_find_catch_block_from_code = mod->getFunction("art_portable_find_catch_block_from_code");
+if (!func_art_portable_find_catch_block_from_code) {
+func_art_portable_find_catch_block_from_code = Function::Create(
+ /*Type=*/FuncTy_12,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_find_catch_block_from_code", mod); // (external, no body)
+func_art_portable_find_catch_block_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_find_catch_block_from_code_PAL;
+func_art_portable_find_catch_block_from_code->setAttributes(func_art_portable_find_catch_block_from_code_PAL);
+
+Function* func_art_portable_alloc_object_from_code = mod->getFunction("art_portable_alloc_object_from_code");
+if (!func_art_portable_alloc_object_from_code) {
+func_art_portable_alloc_object_from_code = Function::Create(
+ /*Type=*/FuncTy_13,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_alloc_object_from_code", mod); // (external, no body)
+func_art_portable_alloc_object_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_alloc_object_from_code_PAL;
+func_art_portable_alloc_object_from_code->setAttributes(func_art_portable_alloc_object_from_code_PAL);
+
+Function* func_art_portable_alloc_object_from_code_with_access_check = mod->getFunction("art_portable_alloc_object_from_code_with_access_check");
+if (!func_art_portable_alloc_object_from_code_with_access_check) {
+func_art_portable_alloc_object_from_code_with_access_check = Function::Create(
+ /*Type=*/FuncTy_13,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_alloc_object_from_code_with_access_check", mod); // (external, no body)
+func_art_portable_alloc_object_from_code_with_access_check->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_alloc_object_from_code_with_access_check_PAL;
+func_art_portable_alloc_object_from_code_with_access_check->setAttributes(func_art_portable_alloc_object_from_code_with_access_check_PAL);
+
+Function* func_art_portable_alloc_array_from_code = mod->getFunction("art_portable_alloc_array_from_code");
+if (!func_art_portable_alloc_array_from_code) {
+func_art_portable_alloc_array_from_code = Function::Create(
+ /*Type=*/FuncTy_14,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_alloc_array_from_code", mod); // (external, no body)
+func_art_portable_alloc_array_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_alloc_array_from_code_PAL;
+func_art_portable_alloc_array_from_code->setAttributes(func_art_portable_alloc_array_from_code_PAL);
+
+Function* func_art_portable_alloc_array_from_code_with_access_check = mod->getFunction("art_portable_alloc_array_from_code_with_access_check");
+if (!func_art_portable_alloc_array_from_code_with_access_check) {
+func_art_portable_alloc_array_from_code_with_access_check = Function::Create(
+ /*Type=*/FuncTy_14,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_alloc_array_from_code_with_access_check", mod); // (external, no body)
+func_art_portable_alloc_array_from_code_with_access_check->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_alloc_array_from_code_with_access_check_PAL;
+func_art_portable_alloc_array_from_code_with_access_check->setAttributes(func_art_portable_alloc_array_from_code_with_access_check_PAL);
+
+Function* func_art_portable_check_and_alloc_array_from_code = mod->getFunction("art_portable_check_and_alloc_array_from_code");
+if (!func_art_portable_check_and_alloc_array_from_code) {
+func_art_portable_check_and_alloc_array_from_code = Function::Create(
+ /*Type=*/FuncTy_14,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_check_and_alloc_array_from_code", mod); // (external, no body)
+func_art_portable_check_and_alloc_array_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_check_and_alloc_array_from_code_PAL;
+func_art_portable_check_and_alloc_array_from_code->setAttributes(func_art_portable_check_and_alloc_array_from_code_PAL);
+
+Function* func_art_portable_check_and_alloc_array_from_code_with_access_check = mod->getFunction("art_portable_check_and_alloc_array_from_code_with_access_check");
+if (!func_art_portable_check_and_alloc_array_from_code_with_access_check) {
+func_art_portable_check_and_alloc_array_from_code_with_access_check = Function::Create(
+ /*Type=*/FuncTy_14,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_check_and_alloc_array_from_code_with_access_check", mod); // (external, no body)
+func_art_portable_check_and_alloc_array_from_code_with_access_check->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_check_and_alloc_array_from_code_with_access_check_PAL;
+func_art_portable_check_and_alloc_array_from_code_with_access_check->setAttributes(func_art_portable_check_and_alloc_array_from_code_with_access_check_PAL);
+
+Function* func_art_portable_find_instance_field_from_code = mod->getFunction("art_portable_find_instance_field_from_code");
+if (!func_art_portable_find_instance_field_from_code) {
+func_art_portable_find_instance_field_from_code = Function::Create(
+ /*Type=*/FuncTy_15,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_find_instance_field_from_code", mod); // (external, no body)
+func_art_portable_find_instance_field_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_find_instance_field_from_code_PAL;
+func_art_portable_find_instance_field_from_code->setAttributes(func_art_portable_find_instance_field_from_code_PAL);
+
+Function* func_art_portable_find_static_field_from_code = mod->getFunction("art_portable_find_static_field_from_code");
+if (!func_art_portable_find_static_field_from_code) {
+func_art_portable_find_static_field_from_code = Function::Create(
+ /*Type=*/FuncTy_15,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_find_static_field_from_code", mod); // (external, no body)
+func_art_portable_find_static_field_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_find_static_field_from_code_PAL;
+func_art_portable_find_static_field_from_code->setAttributes(func_art_portable_find_static_field_from_code_PAL);
+
+Function* func_art_portable_find_static_method_from_code_with_access_check = mod->getFunction("art_portable_find_static_method_from_code_with_access_check");
+if (!func_art_portable_find_static_method_from_code_with_access_check) {
+func_art_portable_find_static_method_from_code_with_access_check = Function::Create(
+ /*Type=*/FuncTy_16,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_find_static_method_from_code_with_access_check", mod); // (external, no body)
+func_art_portable_find_static_method_from_code_with_access_check->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_find_static_method_from_code_with_access_check_PAL;
+func_art_portable_find_static_method_from_code_with_access_check->setAttributes(func_art_portable_find_static_method_from_code_with_access_check_PAL);
+
+Function* func_art_portable_find_direct_method_from_code_with_access_check = mod->getFunction("art_portable_find_direct_method_from_code_with_access_check");
+if (!func_art_portable_find_direct_method_from_code_with_access_check) {
+func_art_portable_find_direct_method_from_code_with_access_check = Function::Create(
+ /*Type=*/FuncTy_16,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_find_direct_method_from_code_with_access_check", mod); // (external, no body)
+func_art_portable_find_direct_method_from_code_with_access_check->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_find_direct_method_from_code_with_access_check_PAL;
+func_art_portable_find_direct_method_from_code_with_access_check->setAttributes(func_art_portable_find_direct_method_from_code_with_access_check_PAL);
+
+Function* func_art_portable_find_virtual_method_from_code_with_access_check = mod->getFunction("art_portable_find_virtual_method_from_code_with_access_check");
+if (!func_art_portable_find_virtual_method_from_code_with_access_check) {
+func_art_portable_find_virtual_method_from_code_with_access_check = Function::Create(
+ /*Type=*/FuncTy_16,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_find_virtual_method_from_code_with_access_check", mod); // (external, no body)
+func_art_portable_find_virtual_method_from_code_with_access_check->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_find_virtual_method_from_code_with_access_check_PAL;
+func_art_portable_find_virtual_method_from_code_with_access_check->setAttributes(func_art_portable_find_virtual_method_from_code_with_access_check_PAL);
+
+Function* func_art_portable_find_super_method_from_code_with_access_check = mod->getFunction("art_portable_find_super_method_from_code_with_access_check");
+if (!func_art_portable_find_super_method_from_code_with_access_check) {
+func_art_portable_find_super_method_from_code_with_access_check = Function::Create(
+ /*Type=*/FuncTy_16,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_find_super_method_from_code_with_access_check", mod); // (external, no body)
+func_art_portable_find_super_method_from_code_with_access_check->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_find_super_method_from_code_with_access_check_PAL;
+func_art_portable_find_super_method_from_code_with_access_check->setAttributes(func_art_portable_find_super_method_from_code_with_access_check_PAL);
+
+Function* func_art_portable_find_interface_method_from_code_with_access_check = mod->getFunction("art_portable_find_interface_method_from_code_with_access_check");
+if (!func_art_portable_find_interface_method_from_code_with_access_check) {
+func_art_portable_find_interface_method_from_code_with_access_check = Function::Create(
+ /*Type=*/FuncTy_16,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_find_interface_method_from_code_with_access_check", mod); // (external, no body)
+func_art_portable_find_interface_method_from_code_with_access_check->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_find_interface_method_from_code_with_access_check_PAL;
+func_art_portable_find_interface_method_from_code_with_access_check->setAttributes(func_art_portable_find_interface_method_from_code_with_access_check_PAL);
+
+Function* func_art_portable_find_interface_method_from_code = mod->getFunction("art_portable_find_interface_method_from_code");
+if (!func_art_portable_find_interface_method_from_code) {
+func_art_portable_find_interface_method_from_code = Function::Create(
+ /*Type=*/FuncTy_16,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_find_interface_method_from_code", mod); // (external, no body)
+func_art_portable_find_interface_method_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_find_interface_method_from_code_PAL;
+func_art_portable_find_interface_method_from_code->setAttributes(func_art_portable_find_interface_method_from_code_PAL);
+
+Function* func_art_portable_initialize_static_storage_from_code = mod->getFunction("art_portable_initialize_static_storage_from_code");
+if (!func_art_portable_initialize_static_storage_from_code) {
+func_art_portable_initialize_static_storage_from_code = Function::Create(
+ /*Type=*/FuncTy_13,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_initialize_static_storage_from_code", mod); // (external, no body)
+func_art_portable_initialize_static_storage_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_initialize_static_storage_from_code_PAL;
+func_art_portable_initialize_static_storage_from_code->setAttributes(func_art_portable_initialize_static_storage_from_code_PAL);
+
+Function* func_art_portable_initialize_type_from_code = mod->getFunction("art_portable_initialize_type_from_code");
+if (!func_art_portable_initialize_type_from_code) {
+func_art_portable_initialize_type_from_code = Function::Create(
+ /*Type=*/FuncTy_13,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_initialize_type_from_code", mod); // (external, no body)
+func_art_portable_initialize_type_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_initialize_type_from_code_PAL;
+func_art_portable_initialize_type_from_code->setAttributes(func_art_portable_initialize_type_from_code_PAL);
+
+Function* func_art_portable_initialize_type_and_verify_access_from_code = mod->getFunction("art_portable_initialize_type_and_verify_access_from_code");
+if (!func_art_portable_initialize_type_and_verify_access_from_code) {
+func_art_portable_initialize_type_and_verify_access_from_code = Function::Create(
+ /*Type=*/FuncTy_13,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_initialize_type_and_verify_access_from_code", mod); // (external, no body)
+func_art_portable_initialize_type_and_verify_access_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_initialize_type_and_verify_access_from_code_PAL;
+func_art_portable_initialize_type_and_verify_access_from_code->setAttributes(func_art_portable_initialize_type_and_verify_access_from_code_PAL);
+
+Function* func_art_portable_resolve_string_from_code = mod->getFunction("art_portable_resolve_string_from_code");
+if (!func_art_portable_resolve_string_from_code) {
+func_art_portable_resolve_string_from_code = Function::Create(
+ /*Type=*/FuncTy_17,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_resolve_string_from_code", mod); // (external, no body)
+func_art_portable_resolve_string_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_resolve_string_from_code_PAL;
+func_art_portable_resolve_string_from_code->setAttributes(func_art_portable_resolve_string_from_code_PAL);
+
+Function* func_art_portable_set32_static_from_code = mod->getFunction("art_portable_set32_static_from_code");
+if (!func_art_portable_set32_static_from_code) {
+func_art_portable_set32_static_from_code = Function::Create(
+ /*Type=*/FuncTy_18,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_set32_static_from_code", mod); // (external, no body)
+func_art_portable_set32_static_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_set32_static_from_code_PAL;
+func_art_portable_set32_static_from_code->setAttributes(func_art_portable_set32_static_from_code_PAL);
+
+Function* func_art_portable_set64_static_from_code = mod->getFunction("art_portable_set64_static_from_code");
+if (!func_art_portable_set64_static_from_code) {
+func_art_portable_set64_static_from_code = Function::Create(
+ /*Type=*/FuncTy_19,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_set64_static_from_code", mod); // (external, no body)
+func_art_portable_set64_static_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_set64_static_from_code_PAL;
+func_art_portable_set64_static_from_code->setAttributes(func_art_portable_set64_static_from_code_PAL);
+
+Function* func_art_portable_set_obj_static_from_code = mod->getFunction("art_portable_set_obj_static_from_code");
+if (!func_art_portable_set_obj_static_from_code) {
+func_art_portable_set_obj_static_from_code = Function::Create(
+ /*Type=*/FuncTy_20,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_set_obj_static_from_code", mod); // (external, no body)
+func_art_portable_set_obj_static_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_set_obj_static_from_code_PAL;
+func_art_portable_set_obj_static_from_code->setAttributes(func_art_portable_set_obj_static_from_code_PAL);
+
+Function* func_art_portable_get32_static_from_code = mod->getFunction("art_portable_get32_static_from_code");
+if (!func_art_portable_get32_static_from_code) {
+func_art_portable_get32_static_from_code = Function::Create(
+ /*Type=*/FuncTy_21,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_get32_static_from_code", mod); // (external, no body)
+func_art_portable_get32_static_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_get32_static_from_code_PAL;
+func_art_portable_get32_static_from_code->setAttributes(func_art_portable_get32_static_from_code_PAL);
+
+Function* func_art_portable_get64_static_from_code = mod->getFunction("art_portable_get64_static_from_code");
+if (!func_art_portable_get64_static_from_code) {
+func_art_portable_get64_static_from_code = Function::Create(
+ /*Type=*/FuncTy_22,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_get64_static_from_code", mod); // (external, no body)
+func_art_portable_get64_static_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_get64_static_from_code_PAL;
+func_art_portable_get64_static_from_code->setAttributes(func_art_portable_get64_static_from_code_PAL);
+
+Function* func_art_portable_get_obj_static_from_code = mod->getFunction("art_portable_get_obj_static_from_code");
+if (!func_art_portable_get_obj_static_from_code) {
+func_art_portable_get_obj_static_from_code = Function::Create(
+ /*Type=*/FuncTy_23,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_get_obj_static_from_code", mod); // (external, no body)
+func_art_portable_get_obj_static_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_get_obj_static_from_code_PAL;
+func_art_portable_get_obj_static_from_code->setAttributes(func_art_portable_get_obj_static_from_code_PAL);
+
+Function* func_art_portable_set32_instance_from_code = mod->getFunction("art_portable_set32_instance_from_code");
+if (!func_art_portable_set32_instance_from_code) {
+func_art_portable_set32_instance_from_code = Function::Create(
+ /*Type=*/FuncTy_24,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_set32_instance_from_code", mod); // (external, no body)
+func_art_portable_set32_instance_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_set32_instance_from_code_PAL;
+func_art_portable_set32_instance_from_code->setAttributes(func_art_portable_set32_instance_from_code_PAL);
+
+Function* func_art_portable_set64_instance_from_code = mod->getFunction("art_portable_set64_instance_from_code");
+if (!func_art_portable_set64_instance_from_code) {
+func_art_portable_set64_instance_from_code = Function::Create(
+ /*Type=*/FuncTy_25,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_set64_instance_from_code", mod); // (external, no body)
+func_art_portable_set64_instance_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_set64_instance_from_code_PAL;
+func_art_portable_set64_instance_from_code->setAttributes(func_art_portable_set64_instance_from_code_PAL);
+
+Function* func_art_portable_set_obj_instance_from_code = mod->getFunction("art_portable_set_obj_instance_from_code");
+if (!func_art_portable_set_obj_instance_from_code) {
+func_art_portable_set_obj_instance_from_code = Function::Create(
+ /*Type=*/FuncTy_26,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_set_obj_instance_from_code", mod); // (external, no body)
+func_art_portable_set_obj_instance_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_set_obj_instance_from_code_PAL;
+func_art_portable_set_obj_instance_from_code->setAttributes(func_art_portable_set_obj_instance_from_code_PAL);
+
+Function* func_art_portable_get32_instance_from_code = mod->getFunction("art_portable_get32_instance_from_code");
+if (!func_art_portable_get32_instance_from_code) {
+func_art_portable_get32_instance_from_code = Function::Create(
+ /*Type=*/FuncTy_20,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_get32_instance_from_code", mod); // (external, no body)
+func_art_portable_get32_instance_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_get32_instance_from_code_PAL;
+func_art_portable_get32_instance_from_code->setAttributes(func_art_portable_get32_instance_from_code_PAL);
+
+Function* func_art_portable_get64_instance_from_code = mod->getFunction("art_portable_get64_instance_from_code");
+if (!func_art_portable_get64_instance_from_code) {
+func_art_portable_get64_instance_from_code = Function::Create(
+ /*Type=*/FuncTy_27,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_get64_instance_from_code", mod); // (external, no body)
+func_art_portable_get64_instance_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_get64_instance_from_code_PAL;
+func_art_portable_get64_instance_from_code->setAttributes(func_art_portable_get64_instance_from_code_PAL);
+
+Function* func_art_portable_get_obj_instance_from_code = mod->getFunction("art_portable_get_obj_instance_from_code");
+if (!func_art_portable_get_obj_instance_from_code) {
+func_art_portable_get_obj_instance_from_code = Function::Create(
+ /*Type=*/FuncTy_13,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_get_obj_instance_from_code", mod); // (external, no body)
+func_art_portable_get_obj_instance_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_get_obj_instance_from_code_PAL;
+func_art_portable_get_obj_instance_from_code->setAttributes(func_art_portable_get_obj_instance_from_code_PAL);
+
+Function* func_art_portable_decode_jobject_in_thread = mod->getFunction("art_portable_decode_jobject_in_thread");
+if (!func_art_portable_decode_jobject_in_thread) {
+func_art_portable_decode_jobject_in_thread = Function::Create(
+ /*Type=*/FuncTy_28,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_decode_jobject_in_thread", mod); // (external, no body)
+func_art_portable_decode_jobject_in_thread->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_decode_jobject_in_thread_PAL;
+func_art_portable_decode_jobject_in_thread->setAttributes(func_art_portable_decode_jobject_in_thread_PAL);
+
+Function* func_art_portable_fill_array_data_from_code = mod->getFunction("art_portable_fill_array_data_from_code");
+if (!func_art_portable_fill_array_data_from_code) {
+func_art_portable_fill_array_data_from_code = Function::Create(
+ /*Type=*/FuncTy_29,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_fill_array_data_from_code", mod); // (external, no body)
+func_art_portable_fill_array_data_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_fill_array_data_from_code_PAL;
+func_art_portable_fill_array_data_from_code->setAttributes(func_art_portable_fill_array_data_from_code_PAL);
+
+Function* func_art_portable_is_assignable_from_code = mod->getFunction("art_portable_is_assignable_from_code");
+if (!func_art_portable_is_assignable_from_code) {
+func_art_portable_is_assignable_from_code = Function::Create(
+ /*Type=*/FuncTy_30,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_is_assignable_from_code", mod); // (external, no body)
+func_art_portable_is_assignable_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_is_assignable_from_code_PAL;
+func_art_portable_is_assignable_from_code->setAttributes(func_art_portable_is_assignable_from_code_PAL);
+
+Function* func_art_portable_check_cast_from_code = mod->getFunction("art_portable_check_cast_from_code");
+if (!func_art_portable_check_cast_from_code) {
+func_art_portable_check_cast_from_code = Function::Create(
+ /*Type=*/FuncTy_5,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_check_cast_from_code", mod); // (external, no body)
+func_art_portable_check_cast_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_check_cast_from_code_PAL;
+func_art_portable_check_cast_from_code->setAttributes(func_art_portable_check_cast_from_code_PAL);
+
+Function* func_art_portable_check_put_array_element_from_code = mod->getFunction("art_portable_check_put_array_element_from_code");
+if (!func_art_portable_check_put_array_element_from_code) {
+func_art_portable_check_put_array_element_from_code = Function::Create(
+ /*Type=*/FuncTy_5,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_check_put_array_element_from_code", mod); // (external, no body)
+func_art_portable_check_put_array_element_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_check_put_array_element_from_code_PAL;
+func_art_portable_check_put_array_element_from_code->setAttributes(func_art_portable_check_put_array_element_from_code_PAL);
+
+Function* func_art_d2l = mod->getFunction("art_d2l");
+if (!func_art_d2l) {
+func_art_d2l = Function::Create(
+ /*Type=*/FuncTy_31,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_d2l", mod); // (external, no body)
+func_art_d2l->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_d2l_PAL;
+func_art_d2l->setAttributes(func_art_d2l_PAL);
+
+Function* func_art_d2i = mod->getFunction("art_d2i");
+if (!func_art_d2i) {
+func_art_d2i = Function::Create(
+ /*Type=*/FuncTy_32,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_d2i", mod); // (external, no body)
+func_art_d2i->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_d2i_PAL;
+func_art_d2i->setAttributes(func_art_d2i_PAL);
+
+Function* func_art_f2l = mod->getFunction("art_f2l");
+if (!func_art_f2l) {
+func_art_f2l = Function::Create(
+ /*Type=*/FuncTy_33,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_f2l", mod); // (external, no body)
+func_art_f2l->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_f2l_PAL;
+func_art_f2l->setAttributes(func_art_f2l_PAL);
+
+Function* func_art_f2i = mod->getFunction("art_f2i");
+if (!func_art_f2i) {
+func_art_f2i = Function::Create(
+ /*Type=*/FuncTy_34,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_f2i", mod); // (external, no body)
+func_art_f2i->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_f2i_PAL;
+func_art_f2i->setAttributes(func_art_f2i_PAL);
+
+Function* func_art_portable_jni_method_start = mod->getFunction("art_portable_jni_method_start");
+if (!func_art_portable_jni_method_start) {
+func_art_portable_jni_method_start = Function::Create(
+ /*Type=*/FuncTy_35,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_jni_method_start", mod); // (external, no body)
+func_art_portable_jni_method_start->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_jni_method_start_PAL;
+func_art_portable_jni_method_start->setAttributes(func_art_portable_jni_method_start_PAL);
+
+Function* func_art_portable_jni_method_start_synchronized = mod->getFunction("art_portable_jni_method_start_synchronized");
+if (!func_art_portable_jni_method_start_synchronized) {
+func_art_portable_jni_method_start_synchronized = Function::Create(
+ /*Type=*/FuncTy_30,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_jni_method_start_synchronized", mod); // (external, no body)
+func_art_portable_jni_method_start_synchronized->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_jni_method_start_synchronized_PAL;
+func_art_portable_jni_method_start_synchronized->setAttributes(func_art_portable_jni_method_start_synchronized_PAL);
+
+Function* func_art_portable_jni_method_end = mod->getFunction("art_portable_jni_method_end");
+if (!func_art_portable_jni_method_end) {
+func_art_portable_jni_method_end = Function::Create(
+ /*Type=*/FuncTy_15,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_jni_method_end", mod); // (external, no body)
+func_art_portable_jni_method_end->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_jni_method_end_PAL;
+func_art_portable_jni_method_end->setAttributes(func_art_portable_jni_method_end_PAL);
+
+Function* func_art_portable_jni_method_end_synchronized = mod->getFunction("art_portable_jni_method_end_synchronized");
+if (!func_art_portable_jni_method_end_synchronized) {
+func_art_portable_jni_method_end_synchronized = Function::Create(
+ /*Type=*/FuncTy_36,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_jni_method_end_synchronized", mod); // (external, no body)
+func_art_portable_jni_method_end_synchronized->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_jni_method_end_synchronized_PAL;
+func_art_portable_jni_method_end_synchronized->setAttributes(func_art_portable_jni_method_end_synchronized_PAL);
+
+Function* func_art_portable_jni_method_end_with_reference = mod->getFunction("art_portable_jni_method_end_with_reference");
+if (!func_art_portable_jni_method_end_with_reference) {
+func_art_portable_jni_method_end_with_reference = Function::Create(
+ /*Type=*/FuncTy_37,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_jni_method_end_with_reference", mod); // (external, no body)
+func_art_portable_jni_method_end_with_reference->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_jni_method_end_with_reference_PAL;
+func_art_portable_jni_method_end_with_reference->setAttributes(func_art_portable_jni_method_end_with_reference_PAL);
+
+Function* func_art_portable_jni_method_end_with_reference_synchronized = mod->getFunction("art_portable_jni_method_end_with_reference_synchronized");
+if (!func_art_portable_jni_method_end_with_reference_synchronized) {
+func_art_portable_jni_method_end_with_reference_synchronized = Function::Create(
+ /*Type=*/FuncTy_38,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_jni_method_end_with_reference_synchronized", mod); // (external, no body)
+func_art_portable_jni_method_end_with_reference_synchronized->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_jni_method_end_with_reference_synchronized_PAL;
+func_art_portable_jni_method_end_with_reference_synchronized->setAttributes(func_art_portable_jni_method_end_with_reference_synchronized_PAL);
+
+Function* func_art_portable_is_exception_pending_from_code = mod->getFunction("art_portable_is_exception_pending_from_code");
+if (!func_art_portable_is_exception_pending_from_code) {
+func_art_portable_is_exception_pending_from_code = Function::Create(
+ /*Type=*/FuncTy_39,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_is_exception_pending_from_code", mod); // (external, no body)
+func_art_portable_is_exception_pending_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_is_exception_pending_from_code_PAL;
+func_art_portable_is_exception_pending_from_code->setAttributes(func_art_portable_is_exception_pending_from_code_PAL);
+
+Function* func_art_portable_mark_gc_card_from_code = mod->getFunction("art_portable_mark_gc_card_from_code");
+if (!func_art_portable_mark_gc_card_from_code) {
+func_art_portable_mark_gc_card_from_code = Function::Create(
+ /*Type=*/FuncTy_5,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_mark_gc_card_from_code", mod); // (external, no body)
+func_art_portable_mark_gc_card_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_mark_gc_card_from_code_PAL;
+func_art_portable_mark_gc_card_from_code->setAttributes(func_art_portable_mark_gc_card_from_code_PAL);
+
+Function* func_art_portable_proxy_invoke_handler_from_code = mod->getFunction("art_portable_proxy_invoke_handler_from_code");
+if (!func_art_portable_proxy_invoke_handler_from_code) {
+func_art_portable_proxy_invoke_handler_from_code = Function::Create(
+ /*Type=*/FuncTy_40,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"art_portable_proxy_invoke_handler_from_code", mod); // (external, no body)
+func_art_portable_proxy_invoke_handler_from_code->setCallingConv(CallingConv::C);
+}
+AttributeSet func_art_portable_proxy_invoke_handler_from_code_PAL;
+func_art_portable_proxy_invoke_handler_from_code->setAttributes(func_art_portable_proxy_invoke_handler_from_code_PAL);
+
+// Global Variable Declarations
+
+
+// Constant Definitions
+
+// Global Variable Definitions
+
+// Function Definitions
+
+return mod;
+
+}
+
+} // namespace llvm
+} // namespace art
diff --git a/compiler/llvm/intrinsic_func_list.def b/compiler/llvm/intrinsic_func_list.def
new file mode 100644
index 0000000..92537ba
--- /dev/null
+++ b/compiler/llvm/intrinsic_func_list.def
@@ -0,0 +1,1803 @@
+/*
+ * 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.
+ */
+
+// DEF_INTRINSICS_FUNC(ID, NAME, ATTR, RET_TYPE,
+//                     ARG1_TYPE, ARG2_TYPE, ARG3_TYPE, ARG4_TYPE, ARG5_TYPE)
+#ifndef DEF_INTRINSICS_FUNC
+#  error "missing DEF_INTRINSICS_FUNC definition!"
+#endif
+
+#define _EVAL_DEF_INTRINSICS_FUNC(ID, NAME, ATTR, RET_TYPE, ...) \
+    DEF_INTRINSICS_FUNC(ID, NAME, ATTR, RET_TYPE, __VA_ARGS__)
+
+#define _EXPAND_ARG0()                         kNone, kNone, kNone, kNone, kNone
+#define _EXPAND_ARG1(ARG1)                      ARG1, kNone, kNone, kNone, kNone
+#define _EXPAND_ARG2(ARG1, ARG2)                ARG1,  ARG2, kNone, kNone, kNone
+#define _EXPAND_ARG3(ARG1, ARG2, ARG3)          ARG1,  ARG2,  ARG3, kNone, kNone
+#define _EXPAND_ARG4(ARG1, ARG2, ARG3, ARG4)    ARG1,  ARG2,  ARG3,  ARG4, kNone
+#define _EXPAND_ARG5(ARG1, ARG2, ARG3, ARG4, ARG5) \
+                                                ARG1,  ARG2,  ARG3,  ARG4,  ARG5
+
+#define _JTYPE(TYPE, SPACE) _JTYPE_OF_ ## TYPE ## _UNDER_ ## SPACE
+
+// Note: These should be consistent with the type return from
+// IRBuilder::GetJType([type], kArray).
+#define _JTYPE_OF_kInt1Ty_UNDER_kArray        kInt8Ty
+#define _JTYPE_OF_kInt8Ty_UNDER_kArray        kInt8Ty
+#define _JTYPE_OF_kInt16Ty_UNDER_kArray       kInt16Ty
+#define _JTYPE_OF_kInt32Ty_UNDER_kArray       kInt32Ty
+#define _JTYPE_OF_kInt64Ty_UNDER_kArray       kInt64Ty
+#define _JTYPE_OF_kJavaObjectTy_UNDER_kArray  kJavaObjectTy
+
+// Note: These should be consistent with the type return from
+// IRBuilder::GetJType([type], kField).
+#define _JTYPE_OF_kInt1Ty_UNDER_kField        kInt32Ty
+#define _JTYPE_OF_kInt8Ty_UNDER_kField        kInt32Ty
+#define _JTYPE_OF_kInt16Ty_UNDER_kField       kInt32Ty
+#define _JTYPE_OF_kInt32Ty_UNDER_kField       kInt32Ty
+#define _JTYPE_OF_kInt64Ty_UNDER_kField       kInt64Ty
+#define _JTYPE_OF_kJavaObjectTy_UNDER_kField  kJavaObjectTy
+
+//----------------------------------------------------------------------------
+// Thread
+//----------------------------------------------------------------------------
+
+// Thread* art_portable_get_current_thread()
+_EVAL_DEF_INTRINSICS_FUNC(GetCurrentThread,
+                          art_portable_get_current_thread,
+                          kAttrReadNone | kAttrNoThrow,
+                          kJavaThreadTy,
+                          _EXPAND_ARG0())
+
+// void art_portable_test_suspend(Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(TestSuspend,
+                          art_portable_test_suspend,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG1(kJavaThreadTy))
+
+// void art_portable_check_suspend() /* Expands to GetCurrentThread/TestSuspend */
+_EVAL_DEF_INTRINSICS_FUNC(CheckSuspend,
+                          art_portable_check_suspend,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG0())
+
+// void art_portable_mark_gc_card(Object* new_value, Object* object)
+_EVAL_DEF_INTRINSICS_FUNC(MarkGCCard,
+                          art_portable_mark_gc_card,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kJavaObjectTy, kJavaObjectTy))
+
+//----------------------------------------------------------------------------
+// Exception
+//----------------------------------------------------------------------------
+
+// Should not expand - introduces the catch targets for a potentially
+// throwing instruction.  The result is a switch key and this
+// instruction will be followed by a switch statement.  The catch
+// targets will be enumerated as cases of the switch, with the fallthrough
+// designating the block containing the potentially throwing instruction.
+// bool art_portable_catch_targets(int dex_pc)
+_EVAL_DEF_INTRINSICS_FUNC(CatchTargets,
+                          art_portable_catch_targets,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kInt32ConstantTy))
+
+// void art_portable_throw_exception(JavaObject* exception)
+_EVAL_DEF_INTRINSICS_FUNC(ThrowException,
+                          art_portable_throw_exception,
+                          kAttrDoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG1(kJavaObjectTy))
+
+// void art_portable_hl_throw_exception(JavaObject* exception)
+_EVAL_DEF_INTRINSICS_FUNC(HLThrowException,
+                          art_portable_hl_throw_exception,
+                          kAttrDoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG1(kJavaObjectTy))
+
+// JavaObject* art_portable_get_current_exception()
+_EVAL_DEF_INTRINSICS_FUNC(GetException,
+                          art_portable_get_current_exception,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kJavaObjectTy,
+                          _EXPAND_ARG0())
+
+// bool art_portable_is_exception_pending()
+_EVAL_DEF_INTRINSICS_FUNC(IsExceptionPending,
+                          art_portable_is_exception_pending,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt1Ty,
+                          _EXPAND_ARG0())
+
+// int art_portable_find_catch_block(Method* method, int try_item_offset)
+_EVAL_DEF_INTRINSICS_FUNC(FindCatchBlock,
+                          art_portable_find_catch_block,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kJavaMethodTy, kInt32ConstantTy))
+
+// void art_portable_throw_div_zero()
+_EVAL_DEF_INTRINSICS_FUNC(ThrowDivZeroException,
+                          art_portable_throw_div_zero,
+                          kAttrDoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG0())
+
+// void art_portable_throw_null_pointer_exception(uint32_t dex_pc)
+_EVAL_DEF_INTRINSICS_FUNC(ThrowNullPointerException,
+                          art_portable_throw_null_pointer_exception,
+                          kAttrDoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG1(kInt32ConstantTy))
+
+// void art_portable_throw_array_bounds(int index, int array_len)
+_EVAL_DEF_INTRINSICS_FUNC(ThrowIndexOutOfBounds,
+                          art_portable_throw_array_bounds,
+                          kAttrDoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32Ty, kInt32Ty))
+
+//----------------------------------------------------------------------------
+// ConstString
+//----------------------------------------------------------------------------
+
+// JavaObject* art_portable_const_string(uint32_t string_idx)
+_EVAL_DEF_INTRINSICS_FUNC(ConstString,
+                          art_portable_const_string,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kJavaObjectTy,
+                          _EXPAND_ARG1(kInt32ConstantTy))
+
+// JavaObject* art_portable_load_string_from_dex_cache(Method* method, uint32_t string_idx)
+_EVAL_DEF_INTRINSICS_FUNC(LoadStringFromDexCache,
+                          art_portable_load_string_from_dex_cache,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kJavaObjectTy,
+                          _EXPAND_ARG1(kInt32ConstantTy))
+
+// JavaObject* art_portable_resolve_string(Method* method, uint32_t string_idx)
+_EVAL_DEF_INTRINSICS_FUNC(ResolveString,
+                          art_portable_resolve_string,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG2(kJavaMethodTy, kInt32ConstantTy))
+
+//----------------------------------------------------------------------------
+// ConstClass
+//----------------------------------------------------------------------------
+
+// JavaObject* art_portable_const_class(uint32_t type_idx)
+_EVAL_DEF_INTRINSICS_FUNC(ConstClass,
+                          art_portable_const_class,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kJavaObjectTy,
+                          _EXPAND_ARG1(kInt32ConstantTy))
+
+// JavaObject* art_portable_initialize_type_and_verify_access(uint32_t type_idx,
+//                                                        Method* referrer,
+//                                                        Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(InitializeTypeAndVerifyAccess,
+                          art_portable_initialize_type_and_verify_access,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaThreadTy))
+
+// JavaObject* art_portable_load_type_from_dex_cache(uint32_t type_idx)
+_EVAL_DEF_INTRINSICS_FUNC(LoadTypeFromDexCache,
+                          art_portable_load_type_from_dex_cache,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kJavaObjectTy,
+                          _EXPAND_ARG1(kInt32ConstantTy))
+
+// JavaObject* art_portable_initialize_type(uint32_t type_idx,
+//                                      Method* referrer,
+//                                      Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(InitializeType,
+                          art_portable_initialize_type,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaThreadTy))
+
+//----------------------------------------------------------------------------
+// Lock
+//----------------------------------------------------------------------------
+
+// void art_portable_lock_object(JavaObject* obj, Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(LockObject,
+                          art_portable_lock_object,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kJavaObjectTy, kJavaThreadTy))
+
+// void art_portable_unlock_object(JavaObject* obj, Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(UnlockObject,
+                          art_portable_unlock_object,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG2(kJavaObjectTy, kJavaThreadTy))
+
+//----------------------------------------------------------------------------
+// Cast
+//----------------------------------------------------------------------------
+
+// void art_portable_check_cast(JavaObject* dest_type, JavaObject* src_type)
+_EVAL_DEF_INTRINSICS_FUNC(CheckCast,
+                          art_portable_check_cast,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG2(kJavaObjectTy, kJavaObjectTy))
+
+// void art_portable_hl_check_cast(uint32_t type_idx, JavaObject* obj)
+_EVAL_DEF_INTRINSICS_FUNC(HLCheckCast,
+                          art_portable_hl_check_cast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32ConstantTy, kJavaObjectTy))
+
+// int art_portable_is_assignable(JavaObject* dest_type, JavaObject* src_type)
+_EVAL_DEF_INTRINSICS_FUNC(IsAssignable,
+                          art_portable_is_assignable,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kJavaObjectTy, kJavaObjectTy))
+
+//----------------------------------------------------------------------------
+// Allocation
+//----------------------------------------------------------------------------
+
+// JavaObject* art_portable_alloc_object(uint32_t type_idx,
+//                                   Method* referrer,
+//                                   Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(AllocObject,
+                          art_portable_alloc_object,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaThreadTy))
+
+// JavaObject* art_portable_alloc_object_with_access_check(uint32_t type_idx,
+//                                                     Method* referrer,
+//                                                     Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(AllocObjectWithAccessCheck,
+                          art_portable_alloc_object_with_access_check,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaThreadTy))
+
+//----------------------------------------------------------------------------
+// Instance
+//----------------------------------------------------------------------------
+
+// JavaObject* art_portable_new_instance(uint32_t type_idx)
+_EVAL_DEF_INTRINSICS_FUNC(NewInstance,
+                          art_portable_new_instance,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG1(kInt32Ty))
+
+// bool art_portable_instance_of(uint32_t type_idx, JavaObject* ref)
+_EVAL_DEF_INTRINSICS_FUNC(InstanceOf,
+                          art_portable_instance_of,
+                          kAttrNone,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kInt32Ty, kJavaObjectTy))
+
+//----------------------------------------------------------------------------
+// Array
+//----------------------------------------------------------------------------
+
+// JavaObject* art_portable_new_array(uint32_t type_idx, uint32_t array_size)
+_EVAL_DEF_INTRINSICS_FUNC(NewArray,
+                          art_portable_new_array,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG2(kInt32ConstantTy, kInt32Ty))
+
+// uint32_t art_portable_opt_array_length(int32_t opt_flags, JavaObject* array)
+_EVAL_DEF_INTRINSICS_FUNC(OptArrayLength,
+                          art_portable_opt_array_length,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kInt32Ty, kJavaObjectTy))
+
+// uint32_t art_portable_array_length(JavaObject* array)
+_EVAL_DEF_INTRINSICS_FUNC(ArrayLength,
+                          art_portable_array_length,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kJavaObjectTy))
+
+// JavaObject* art_portable_alloc_array(uint32_t type_idx,
+//                                  Method* referrer,
+//                                  uint32_t length,
+//                                  Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(AllocArray,
+                          art_portable_alloc_array,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kInt32Ty, kJavaThreadTy))
+
+// JavaObject* art_portable_alloc_array_with_access_check(uint32_t type_idx,
+//                                                    Method* referrer,
+//                                                    uint32_t length,
+//                                                    Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(AllocArrayWithAccessCheck,
+                          art_portable_alloc_array_with_access_check,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kInt32Ty, kJavaThreadTy))
+
+// JavaObject* art_portable_check_and_alloc_array(uint32_t type_idx,
+//                                            Method* referrer,
+//                                            uint32_t length,
+//                                            Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(CheckAndAllocArray,
+                          art_portable_check_and_alloc_array,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kInt32ConstantTy, kJavaThreadTy))
+
+// JavaObject* art_portable_check_and_alloc_array_with_access_check(uint32_t type_idx,
+//                                                              Method* referrer,
+//                                                              uint32_t length,
+//                                                              Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(CheckAndAllocArrayWithAccessCheck,
+                          art_portable_check_and_alloc_array_with_access_check,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kInt32ConstantTy, kJavaThreadTy))
+
+// art_portable_aget_* and art_portable_aput_* never generate exception since the
+// necessary checking on arguments (e.g., array and index) has already done
+// before invocation of these intrinsics.
+//
+// [type] void art_portable_aget_[type](JavaObject* array, uint32_t index)
+_EVAL_DEF_INTRINSICS_FUNC(ArrayGet,
+                          art_portable_aget,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt32Ty, kArray),
+                          _EXPAND_ARG2(kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(ArrayGetWide,
+                          art_portable_aget_wide,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt64Ty, kArray),
+                          _EXPAND_ARG2(kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(ArrayGetObject,
+                          art_portable_aget_object,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kJavaObjectTy, kArray),
+                          _EXPAND_ARG2(kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(ArrayGetBoolean,
+                          art_portable_aget_boolean,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt1Ty, kArray),
+                          _EXPAND_ARG2(kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(ArrayGetByte,
+                          art_portable_aget_byte,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt8Ty, kArray),
+                          _EXPAND_ARG2(kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(ArrayGetChar,
+                          art_portable_aget_char,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt16Ty, kArray),
+                          _EXPAND_ARG2(kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(ArrayGetShort,
+                          art_portable_aget_short,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt16Ty, kArray),
+                          _EXPAND_ARG2(kJavaObjectTy, kInt32Ty))
+
+// void art_portable_aput_[type]([type] value, JavaObject* array, uint32_t index)
+_EVAL_DEF_INTRINSICS_FUNC(ArrayPut,
+                          art_portable_aput,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG3(_JTYPE(kInt32Ty, kArray), kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(ArrayPutWide,
+                          art_portable_aput_wide,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG3(_JTYPE(kInt64Ty, kArray), kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(ArrayPutObject,
+                          art_portable_aput_object,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG3(_JTYPE(kJavaObjectTy, kArray), kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(ArrayPutBoolean,
+                          art_portable_aput_boolean,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG3(_JTYPE(kInt1Ty, kArray), kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(ArrayPutByte,
+                          art_portable_aput_byte,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG3(_JTYPE(kInt8Ty, kArray), kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(ArrayPutChar,
+                          art_portable_aput_char,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG3(_JTYPE(kInt16Ty, kArray), kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(ArrayPutShort,
+                          art_portable_aput_short,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG3(_JTYPE(kInt16Ty, kArray), kJavaObjectTy, kInt32Ty))
+
+// void art_portable_check_put_array_element(JavaObject* value, JavaObject* array)
+_EVAL_DEF_INTRINSICS_FUNC(CheckPutArrayElement,
+                          art_portable_check_put_array_element,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG2(kJavaObjectTy, kJavaObjectTy))
+
+// void art_portable_filled_new_array(Array* array,
+//                                uint32_t elem_jty, ...)
+_EVAL_DEF_INTRINSICS_FUNC(FilledNewArray,
+                          art_portable_filled_new_array,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG3(kJavaObjectTy, kInt32ConstantTy, kVarArgTy))
+
+// void art_portable_fill_array_data(Method* referrer,
+//                               uint32_t dex_pc,
+//                               Array* array,
+//                               uint32_t payload_offset)
+_EVAL_DEF_INTRINSICS_FUNC(FillArrayData,
+                          art_portable_fill_array_data,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kJavaMethodTy, kInt32ConstantTy, kJavaObjectTy, kInt32ConstantTy))
+
+// void art_portable_hl_fill_array_data(int32_t offset, JavaObject* array)
+_EVAL_DEF_INTRINSICS_FUNC(HLFillArrayData,
+                          art_portable_hl_fill_array_data,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32ConstantTy, kJavaObjectTy))
+
+//----------------------------------------------------------------------------
+// Instance Field
+//----------------------------------------------------------------------------
+
+// [type] art_portable_iget_[type](uint32_t field_idx,
+//                             Method* referrer,
+//                             JavaObject* obj)
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGet,
+                          art_portable_iget,
+                          kAttrNone,
+                          _JTYPE(kInt32Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetWide,
+                          art_portable_iget_wide,
+                          kAttrNone,
+                          _JTYPE(kInt64Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetObject,
+                          art_portable_iget_object,
+                          kAttrNone,
+                          _JTYPE(kJavaObjectTy, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetBoolean,
+                          art_portable_iget_boolean,
+                          kAttrNone,
+                          _JTYPE(kInt1Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetByte,
+                          art_portable_iget_byte,
+                          kAttrNone,
+                          _JTYPE(kInt8Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetChar,
+                          art_portable_iget_char,
+                          kAttrNone,
+                          _JTYPE(kInt16Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetShort,
+                          art_portable_iget_short,
+                          kAttrNone,
+                          _JTYPE(kInt16Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy))
+
+// [type] art_portable_iget_[type].fast(int field_offset,
+//                                  bool is_volatile,
+//                                  JavaObject* obj)
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetFast,
+                          art_portable_iget.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt32Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetWideFast,
+                          art_portable_iget_wide.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt64Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetObjectFast,
+                          art_portable_iget_object.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kJavaObjectTy, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetBooleanFast,
+                          art_portable_iget_boolean.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt1Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetByteFast,
+                          art_portable_iget_byte.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt8Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetCharFast,
+                          art_portable_iget_char.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt16Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldGetShortFast,
+                          art_portable_iget_short.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt16Ty, kField),
+                          _EXPAND_ARG3(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy))
+
+// void art_portable_iput_[type](uint32_t field_idx,
+//                           Method* referrer,
+//                           JavaObject* obj,
+//                           [type] new_value)
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPut,
+                          art_portable_iput,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy, _JTYPE(kInt32Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutWide,
+                          art_portable_iput_wide,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy, _JTYPE(kInt64Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutObject,
+                          art_portable_iput_object,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy, _JTYPE(kJavaObjectTy, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutBoolean,
+                          art_portable_iput_boolean,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy, _JTYPE(kInt1Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutByte,
+                          art_portable_iput_byte,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy, _JTYPE(kInt8Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutChar,
+                          art_portable_iput_char,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy, _JTYPE(kInt16Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutShort,
+                          art_portable_iput_short,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaMethodTy, kJavaObjectTy, _JTYPE(kInt16Ty, kField)))
+
+// void art_portable_iput_[type].fast(int field_offset,
+//                                bool is_volatile,
+//                                JavaObject* obj,
+//                                [type] new_value)
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutFast,
+                          art_portable_iput.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy, _JTYPE(kInt32Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutWideFast,
+                          art_portable_iput_wide.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy, _JTYPE(kInt64Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutObjectFast,
+                          art_portable_iput_object.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy, _JTYPE(kJavaObjectTy, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutBooleanFast,
+                          art_portable_iput_boolean.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy, _JTYPE(kInt1Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutByteFast,
+                          art_portable_iput_byte.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy, _JTYPE(kInt8Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutCharFast,
+                          art_portable_iput_char.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy, _JTYPE(kInt16Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(InstanceFieldPutShortFast,
+                          art_portable_iput_short.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kInt1ConstantTy, kJavaObjectTy, _JTYPE(kInt16Ty, kField)))
+
+//----------------------------------------------------------------------------
+// Static Field
+//----------------------------------------------------------------------------
+
+// [type] art_portable_sget_[type](uint32_t field_idx, Method* referrer)
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldGet,
+                          art_portable_sget,
+                          kAttrNone,
+                          _JTYPE(kInt32Ty, kField),
+                          _EXPAND_ARG2(kInt32ConstantTy, kJavaMethodTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetWide,
+                          art_portable_sget_wide,
+                          kAttrNone,
+                          _JTYPE(kInt64Ty, kField),
+                          _EXPAND_ARG2(kInt32ConstantTy, kJavaMethodTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetObject,
+                          art_portable_sget_object,
+                          kAttrNone,
+                          _JTYPE(kJavaObjectTy, kField),
+                          _EXPAND_ARG2(kInt32ConstantTy, kJavaMethodTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetBoolean,
+                          art_portable_sget_boolean,
+                          kAttrNone,
+                          _JTYPE(kInt1Ty, kField),
+                          _EXPAND_ARG2(kInt32ConstantTy, kJavaMethodTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetByte,
+                          art_portable_sget_byte,
+                          kAttrNone,
+                          _JTYPE(kInt8Ty, kField),
+                          _EXPAND_ARG2(kInt32ConstantTy, kJavaMethodTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetChar,
+                          art_portable_sget_char,
+                          kAttrNone,
+                          _JTYPE(kInt16Ty, kField),
+                          _EXPAND_ARG2(kInt32ConstantTy, kJavaMethodTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetShort,
+                          art_portable_sget_short,
+                          kAttrNone,
+                          _JTYPE(kInt16Ty, kField),
+                          _EXPAND_ARG2(kInt32ConstantTy, kJavaMethodTy))
+
+// [type] art_portable_sget_[type].fast(JavaObject* ssb,
+//                                  int field_offset,
+//                                  bool is_volatile)
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetFast,
+                          art_portable_sget.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt32Ty, kField),
+                          _EXPAND_ARG3(kJavaObjectTy, kInt32ConstantTy, kInt1ConstantTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetWideFast,
+                          art_portable_sget_wide.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt64Ty, kField),
+                          _EXPAND_ARG3(kJavaObjectTy, kInt32ConstantTy, kInt1ConstantTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetObjectFast,
+                          art_portable_sget_object.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kJavaObjectTy, kField),
+                          _EXPAND_ARG3(kJavaObjectTy, kInt32ConstantTy, kInt1ConstantTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetBooleanFast,
+                          art_portable_sget_boolean.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt1Ty, kField),
+                          _EXPAND_ARG3(kJavaObjectTy, kInt32ConstantTy, kInt1ConstantTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetByteFast,
+                          art_portable_sget_byte.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt8Ty, kField),
+                          _EXPAND_ARG3(kJavaObjectTy, kInt32ConstantTy, kInt1ConstantTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetCharFast,
+                          art_portable_sget_char.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt16Ty, kField),
+                          _EXPAND_ARG3(kJavaObjectTy, kInt32ConstantTy, kInt1ConstantTy))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldGetShortFast,
+                          art_portable_sget_short.fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          _JTYPE(kInt16Ty, kField),
+                          _EXPAND_ARG3(kJavaObjectTy, kInt32ConstantTy, kInt1ConstantTy))
+
+// void art_portable_sput_[type](uint32_t field_idx,
+//                           Method* referrer,
+//                           [type] new_value)
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldPut,
+                          art_portable_sput,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, _JTYPE(kInt32Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldPutWide,
+                          art_portable_sput_wide,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, _JTYPE(kInt64Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldPutObject,
+                          art_portable_sput_object,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, _JTYPE(kJavaObjectTy, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldPutBoolean,
+                          art_portable_sput_boolean,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, _JTYPE(kInt1Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldPutByte,
+                          art_portable_sput_byte,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, _JTYPE(kInt8Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldPutChar,
+                          art_portable_sput_char,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, _JTYPE(kInt16Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldPutShort,
+                          art_portable_sput_short,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, _JTYPE(kInt16Ty, kField)))
+
+// void art_portable_sput_[type].fast(JavaObject* ssb,
+//                                int field_offset,
+//                                bool is_volatile,
+//                                [type] new_value)
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldPutFast,
+                          art_portable_sput.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kJavaObjectTy, kInt32ConstantTy, kInt1ConstantTy, _JTYPE(kInt32Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldPutWideFast,
+                          art_portable_sput_wide.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kJavaObjectTy, kInt32ConstantTy, kInt1ConstantTy, _JTYPE(kInt64Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldPutObjectFast,
+                          art_portable_sput_object.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kJavaObjectTy, kInt32ConstantTy, kInt1ConstantTy, _JTYPE(kJavaObjectTy, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldPutBooleanFast,
+                          art_portable_sput_boolean.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kJavaObjectTy, kInt32ConstantTy, kInt1ConstantTy, _JTYPE(kInt1Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldPutByteFast,
+                          art_portable_sput_byte.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kJavaObjectTy, kInt32ConstantTy, kInt1ConstantTy, _JTYPE(kInt8Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldPutCharFast,
+                          art_portable_sput_char.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kJavaObjectTy, kInt32ConstantTy, kInt1ConstantTy, _JTYPE(kInt16Ty, kField)))
+
+_EVAL_DEF_INTRINSICS_FUNC(StaticFieldPutShortFast,
+                          art_portable_sput_short.fast,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kJavaObjectTy, kInt32ConstantTy, kInt1ConstantTy, _JTYPE(kInt16Ty, kField)))
+
+// JavaObject* art_portable_load_declaring_class_ssb(Method* method)
+// Load the static storage base of the class that given method resides
+_EVAL_DEF_INTRINSICS_FUNC(LoadDeclaringClassSSB,
+                          art_portable_load_declaring_class_ssb,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kJavaObjectTy,
+                          _EXPAND_ARG1(kJavaMethodTy))
+
+// JavaObject* art_portable_load_class_ssb_from_dex_cache(uint32_t type_idx)
+_EVAL_DEF_INTRINSICS_FUNC(LoadClassSSBFromDexCache,
+                          art_portable_load_class_ssb_from_dex_cache,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kJavaObjectTy,
+                          _EXPAND_ARG1(kInt32ConstantTy))
+
+// JavaObject* art_portable_init_and_load_class_ssb(uint32_t type_idx,
+//                                              Method* referrer,
+//                                              Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(InitializeAndLoadClassSSB,
+                          art_portable_init_and_load_class_ssb,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG3(kInt32ConstantTy, kJavaMethodTy, kJavaThreadTy))
+
+//----------------------------------------------------------------------------
+// High-level Array get/put
+//
+// Similar to art_portable_aget/aput_xxx, but checks not yet performed.
+// OptFlags contain info describing whether frontend has determined that
+// null check and/or array bounds check may be skipped.
+//
+// [type] void art_portable_hl_aget_[type](int optFlags, JavaObject* array, uint32_t index)
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayGet,
+                          art_portable_hl_aget,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayGetFloat,
+                          art_portable_hl_aget_float,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kFloatTy,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayGetWide,
+                          art_portable_hl_aget_wide,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt64Ty,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayGetDouble,
+                          art_portable_hl_aget_double,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kDoubleTy,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayGetObject,
+                          art_portable_hl_aget_object,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kJavaObjectTy,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayGetBoolean,
+                          art_portable_hl_aget_boolean,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayGetByte,
+                          art_portable_hl_aget_byte,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayGetChar,
+                          art_portable_hl_aget_char,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayGetShort,
+                          art_portable_hl_aget_short,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+// void art_portable_aput_[type](int optFlags, [type] value, JavaObject* array, uint32_t index)
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayPut,
+                          art_portable_hl_aput,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayPutFloat,
+                          art_portable_hl_aput_float,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kFloatTy, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayPutWide,
+                          art_portable_hl_aput_wide,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kInt64Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayPutDouble,
+                          art_portable_hl_aput_double,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kDoubleTy, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayPutObject,
+                          art_portable_hl_aput_object,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kJavaObjectTy, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayPutBoolean,
+                          art_portable_hl_aput_boolean,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayPutByte,
+                          art_portable_hl_aput_byte,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayPutChar,
+                          art_portable_hl_aput_char,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLArrayPutShort,
+                          art_portable_hl_aput_short,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+//----------------------------------------------------------------------------
+// High-level Instance get/put
+//
+// Similar to art_portable_iget/iput_xxx, but checks not yet performed.
+// OptFlags contain info describing whether frontend has determined that
+// null check may be skipped.
+//
+// [type] void art_portable_hl_iget_[type](int optFlags, JavaObject* obj, uint32_t field_idx)
+_EVAL_DEF_INTRINSICS_FUNC(HLIGet,
+                          art_portable_hl_iget,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIGetFloat,
+                          art_portable_hl_iget_float,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kFloatTy,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIGetWide,
+                          art_portable_hl_iget_wide,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt64Ty,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIGetDouble,
+                          art_portable_hl_iget_double,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kDoubleTy,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIGetObject,
+                          art_portable_hl_iget_object,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kJavaObjectTy,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIGetBoolean,
+                          art_portable_hl_iget_boolean,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIGetByte,
+                          art_portable_hl_iget_byte,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIGetChar,
+                          art_portable_hl_iget_char,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIGetShort,
+                          art_portable_hl_iget_short,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG3(kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+// void art_portable_iput_[type](int optFlags, [type] value, JavaObject* obj, uint32_t field_idx)
+_EVAL_DEF_INTRINSICS_FUNC(HLIPut,
+                          art_portable_hl_iput,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIPutFloat,
+                          art_portable_hl_iput_float,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kFloatTy, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIPutWide,
+                          art_portable_hl_iput_wide,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kInt64Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIPutDouble,
+                          art_portable_hl_iput_double,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kDoubleTy, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIPutObject,
+                          art_portable_hl_iput_object,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kJavaObjectTy, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIPutBoolean,
+                          art_portable_hl_iput_boolean,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIPutByte,
+                          art_portable_hl_iput_byte,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIPutChar,
+                          art_portable_hl_iput_char,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(HLIPutShort,
+                          art_portable_hl_iput_short,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG4(kInt32Ty, kInt32Ty, kJavaObjectTy, kInt32Ty))
+
+//----------------------------------------------------------------------------
+// High-level Invokes (fast-path determination not yet performed)
+//
+// NOTE: We expect these intrinsics to be temporary.  Once calling conventions are
+//       fully merged, the unified front end will lower down to the
+//       InvokeRetxxx() intrinsics in the next section and these will be
+//       removed.
+//
+// arg0: InvokeType [ignored if FilledNewArray]
+// arg1: method_idx [ignored if FilledNewArray]
+// arg2: optimization_flags (primary to note whether null checking is needed)
+// [arg3..argN]: actual arguments
+//----------------------------------------------------------------------------
+// INVOKE method returns void
+_EVAL_DEF_INTRINSICS_FUNC(HLInvokeVoid,
+                          art_portable_hl_invoke.void,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG1(kVarArgTy))
+
+// INVOKE method returns object
+_EVAL_DEF_INTRINSICS_FUNC(HLInvokeObj,
+                          art_portable_hl_invoke.obj,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG1(kVarArgTy))
+
+// INVOKE method returns int
+_EVAL_DEF_INTRINSICS_FUNC(HLInvokeInt,
+                          art_portable_hl_invoke.i32,
+                          kAttrNone,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kVarArgTy))
+
+// INVOKE method returns float
+_EVAL_DEF_INTRINSICS_FUNC(HLInvokeFloat,
+                          art_portable_hl_invoke.f32,
+                          kAttrNone,
+                          kFloatTy,
+                          _EXPAND_ARG1(kVarArgTy))
+
+// INVOKE method returns long
+_EVAL_DEF_INTRINSICS_FUNC(HLInvokeLong,
+                          art_portable_hl_invoke.i64,
+                          kAttrNone,
+                          kInt64Ty,
+                          _EXPAND_ARG1(kVarArgTy))
+
+// INVOKE method returns double
+_EVAL_DEF_INTRINSICS_FUNC(HLInvokeDouble,
+                          art_portable_hl_invoke.f64,
+                          kAttrNone,
+                          kDoubleTy,
+                          _EXPAND_ARG1(kVarArgTy))
+
+// FILLED_NEW_ARRAY returns object
+_EVAL_DEF_INTRINSICS_FUNC(HLFilledNewArray,
+                          art_portable_hl_filled_new_array,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG1(kVarArgTy))
+
+//----------------------------------------------------------------------------
+// Invoke
+//----------------------------------------------------------------------------
+
+// Method* art_portable_find_static_method_with_access_check(uint32_t method_idx,
+//                                                       JavaObject* this,
+//                                                       Method* referrer,
+//                                                       Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(FindStaticMethodWithAccessCheck,
+                          art_portable_find_static_method_with_access_check,
+                          kAttrNone,
+                          kJavaMethodTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaObjectTy, kJavaMethodTy, kJavaThreadTy))
+
+// Method* art_portable_find_direct_method_with_access_check(uint32_t method_idx,
+//                                                       JavaObject* this,
+//                                                       Method* referrer,
+//                                                       Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(FindDirectMethodWithAccessCheck,
+                          art_portable_find_direct_method_with_access_check,
+                          kAttrNone,
+                          kJavaMethodTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaObjectTy, kJavaMethodTy, kJavaThreadTy))
+
+// Method* art_portable_find_virtual_method_with_access_check(uint32_t method_idx,
+//                                                        JavaObject* this,
+//                                                        Method* referrer,
+//                                                        Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(FindVirtualMethodWithAccessCheck,
+                          art_portable_find_virtual_method_with_access_check,
+                          kAttrNone,
+                          kJavaMethodTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaObjectTy, kJavaMethodTy, kJavaThreadTy))
+
+// Method* art_portable_find_super_method_with_access_check(uint32_t method_idx,
+//                                                      JavaObject* this,
+//                                                      Method* referrer,
+//                                                      Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(FindSuperMethodWithAccessCheck,
+                          art_portable_find_super_method_with_access_check,
+                          kAttrNone,
+                          kJavaMethodTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaObjectTy, kJavaMethodTy, kJavaThreadTy))
+
+// Method* art_portable_find_interface_method_with_access_check(uint32_t method_idx,
+//                                                          JavaObject* this,
+//                                                          Method* referrer,
+//                                                          Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(FindInterfaceMethodWithAccessCheck,
+                          art_portable_find_interface_method_with_access_check,
+                          kAttrNone,
+                          kJavaMethodTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaObjectTy, kJavaMethodTy, kJavaThreadTy))
+
+// Method* art_portable_get_sd_callee_method_obj_addr(uint32_t method_idx)
+_EVAL_DEF_INTRINSICS_FUNC(GetSDCalleeMethodObjAddrFast,
+                          art_portable_get_sd_callee_method_obj_addr_fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kJavaMethodTy,
+                          _EXPAND_ARG1(kInt32ConstantTy))
+
+// Method* art_portable_get_virtual_callee_method_obj_addr(uint32_t vtable_idx,
+//                                                     JavaObject* this)
+_EVAL_DEF_INTRINSICS_FUNC(GetVirtualCalleeMethodObjAddrFast,
+                          art_portable_get_virtual_callee_method_obj_addr_fast,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kJavaMethodTy,
+                          _EXPAND_ARG2(kInt32ConstantTy, kJavaObjectTy))
+
+// Method* art_portable_get_interface_callee_method_obj_addr(uint32_t method_idx,
+//                                                       JavaObject* this,
+//                                                       Method* referrer,
+//                                                       Thread* thread)
+_EVAL_DEF_INTRINSICS_FUNC(GetInterfaceCalleeMethodObjAddrFast,
+                          art_portable_get_interface_callee_method_obj_addr_fast,
+                          kAttrNone,
+                          kJavaMethodTy,
+                          _EXPAND_ARG4(kInt32ConstantTy, kJavaObjectTy, kJavaMethodTy, kJavaThreadTy))
+
+// [type] art_portable_invoke.[type](Method* callee, ...)
+// INVOKE method returns void
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetVoid,
+                          art_portable_invoke.void,
+                          kAttrNone,
+                          kVoidTy,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+// INVOKE method returns the value of type boolean
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetBoolean,
+                          art_portable_invoke.bool,
+                          kAttrNone,
+                          kInt1Ty,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+// INVOKE method returns the value of type byte
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetByte,
+                          art_portable_invoke.byte,
+                          kAttrNone,
+                          kInt8Ty,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+// INVOKE method returns the value of type char
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetChar,
+                          art_portable_invoke.char,
+                          kAttrNone,
+                          kInt16Ty,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+// INVOKE method returns the value of type short
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetShort,
+                          art_portable_invoke.short,
+                          kAttrNone,
+                          kInt16Ty,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+// INVOKE method returns the value of type int
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetInt,
+                          art_portable_invoke.int,
+                          kAttrNone,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+// INVOKE method returns the value of type long
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetLong,
+                          art_portable_invoke.long,
+                          kAttrNone,
+                          kInt64Ty,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+// INVOKE method returns the value of type float
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetFloat,
+                          art_portable_invoke.float,
+                          kAttrNone,
+                          kFloatTy,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+// INVOKE method returns the value of type double
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetDouble,
+                          art_portable_invoke.double,
+                          kAttrNone,
+                          kDoubleTy,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+// INVOKE method returns the value of type "object"
+_EVAL_DEF_INTRINSICS_FUNC(InvokeRetObject,
+                          art_portable_invoke.object,
+                          kAttrNone,
+                          kJavaObjectTy,
+                          _EXPAND_ARG2(kJavaMethodTy, kVarArgTy))
+
+//----------------------------------------------------------------------------
+// Math
+//----------------------------------------------------------------------------
+
+// int art_portable_{div,rem}_int(int a, int b)
+_EVAL_DEF_INTRINSICS_FUNC(DivInt,
+                          art_portable_div_int,
+                          kAttrReadNone | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kInt32Ty, kInt32Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(RemInt,
+                          art_portable_rem_int,
+                          kAttrReadNone | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kInt32Ty, kInt32Ty))
+
+// long art_portable_{div,rem}_long(long a, long b)
+_EVAL_DEF_INTRINSICS_FUNC(DivLong,
+                          art_portable_div_long,
+                          kAttrReadNone | kAttrNoThrow,
+                          kInt64Ty,
+                          _EXPAND_ARG2(kInt64Ty, kInt64Ty))
+
+_EVAL_DEF_INTRINSICS_FUNC(RemLong,
+                          art_portable_rem_long,
+                          kAttrReadNone | kAttrNoThrow,
+                          kInt64Ty,
+                          _EXPAND_ARG2(kInt64Ty, kInt64Ty))
+
+// int64_t art_portable_d2l(double f)
+_EVAL_DEF_INTRINSICS_FUNC(D2L,
+                          art_portable_d2l,
+                          kAttrReadNone | kAttrNoThrow,
+                          kInt64Ty,
+                          _EXPAND_ARG1(kDoubleTy))
+
+// int32_t art_portable_d2l(double f)
+_EVAL_DEF_INTRINSICS_FUNC(D2I,
+                          art_portable_d2i,
+                          kAttrReadNone | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kDoubleTy))
+
+// int64_t art_portable_f2l(float f)
+_EVAL_DEF_INTRINSICS_FUNC(F2L,
+                          art_portable_f2l,
+                          kAttrReadNone | kAttrNoThrow,
+                          kInt64Ty,
+                          _EXPAND_ARG1(kFloatTy))
+
+// int32_t art_portable_f2i(float f)
+_EVAL_DEF_INTRINSICS_FUNC(F2I,
+                          art_portable_f2i,
+                          kAttrReadNone | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kFloatTy))
+
+//----------------------------------------------------------------------------
+// sput intrinsics to assist MIR to Greenland_ir conversion.
+// "HL" versions - will be deprecated when fast/slow path handling done
+// in the common frontend.
+//----------------------------------------------------------------------------
+
+// void sput_hl(int field_idx, int val)
+_EVAL_DEF_INTRINSICS_FUNC(HLSput,
+                          art_portable_hl_sput,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32Ty, kInt32Ty))
+
+// void sput_hl_object(int field_idx, object* val)
+_EVAL_DEF_INTRINSICS_FUNC(HLSputObject,
+                          art_portable_hl_sput_object,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32Ty, kJavaObjectTy))
+
+// void sput_hl_boolean(int field_idx, kInt1Ty)
+_EVAL_DEF_INTRINSICS_FUNC(HLSputBoolean,
+                          art_portable_hl_sput_boolean,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32Ty, kInt32Ty))
+
+// void sput_hl_byte(int field_idx, int val)
+_EVAL_DEF_INTRINSICS_FUNC(HLSputByte,
+                          art_portable_hl_sput_byte,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32Ty, kInt32Ty))
+
+// void sput_hl_char(int field_idx, kInt16Ty val)
+_EVAL_DEF_INTRINSICS_FUNC(HLSputChar,
+                          art_portable_hl_sput_char,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32Ty, kInt32Ty))
+
+// void sput_hl_short(int field_idx, int val)
+_EVAL_DEF_INTRINSICS_FUNC(HLSputShort,
+                          art_portable_hl_sput_short,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32Ty, kInt32Ty))
+
+// void sput_hl_wide(int field_idx, long val)
+_EVAL_DEF_INTRINSICS_FUNC(HLSputWide,
+                          art_portable_hl_sput_wide,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32Ty, kInt64Ty))
+
+// void sput_hl_double(int field_idx, double val)
+_EVAL_DEF_INTRINSICS_FUNC(HLSputDouble,
+                          art_portable_hl_sput_double,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32Ty, kDoubleTy))
+
+// void sput_hl_float(int field_idx, float val)
+_EVAL_DEF_INTRINSICS_FUNC(HLSputFloat,
+                          art_portable_hl_sput_float,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32Ty, kFloatTy))
+
+//----------------------------------------------------------------------------
+// sget intrinsics to assist MIR to Greenland_ir conversion.
+// "HL" versions - will be deprecated when fast/slow path handling done
+// in the common frontend.
+//----------------------------------------------------------------------------
+
+// int sget_hl(int field_idx)
+_EVAL_DEF_INTRINSICS_FUNC(HLSget,
+                          art_portable_hl_sget,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kInt32Ty))
+
+// object* sget_hl_object(int field_idx)
+_EVAL_DEF_INTRINSICS_FUNC(HLSgetObject,
+                          art_portable_hl_sget_object,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kJavaObjectTy,
+                          _EXPAND_ARG1(kInt32Ty))
+
+// boolean sget_hl_boolean(int field_idx)
+_EVAL_DEF_INTRINSICS_FUNC(HLSgetBoolean,
+                          art_portable_hl_sget_boolean,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kInt32Ty))
+
+// byte sget_hl_byte(int field_idx)
+_EVAL_DEF_INTRINSICS_FUNC(HLSgetByte,
+                          art_portable_hl_sget_byte,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kInt32Ty))
+
+// char sget_hl_char(int field_idx)
+_EVAL_DEF_INTRINSICS_FUNC(HLSgetChar,
+                          art_portable_hl_sget_char,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kInt32Ty))
+
+// char sget_hl_short(int field_idx)
+_EVAL_DEF_INTRINSICS_FUNC(HLSgetShort,
+                          art_portable_hl_sget_short,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kInt32Ty))
+
+// char sget_hl_wide(int field_idx)
+_EVAL_DEF_INTRINSICS_FUNC(HLSgetWide,
+                          art_portable_hl_sget_wide,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt64Ty,
+                          _EXPAND_ARG1(kInt32Ty))
+
+// char sget_hl_double(int field_idx)
+_EVAL_DEF_INTRINSICS_FUNC(HLSgetDouble,
+                          art_portable_hl_sget_double,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kDoubleTy,
+                          _EXPAND_ARG1(kInt32Ty))
+
+// char sget_hl_float(int field_idx)
+_EVAL_DEF_INTRINSICS_FUNC(HLSgetFloat,
+                          art_portable_hl_sget_float,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kFloatTy,
+                          _EXPAND_ARG1(kInt32Ty))
+//----------------------------------------------------------------------------
+// Monitor enter/exit
+//----------------------------------------------------------------------------
+// uint32_t art_portable_monitor_enter(int optFlags, JavaObject* obj)
+_EVAL_DEF_INTRINSICS_FUNC(MonitorEnter,
+                          art_portable_monitor_enter,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32Ty, kJavaObjectTy))
+
+// uint32_t art_portable_monitor_exit(int optFlags, JavaObject* obj)
+_EVAL_DEF_INTRINSICS_FUNC(MonitorExit,
+                          art_portable_monitor_exit,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32Ty, kJavaObjectTy))
+
+//----------------------------------------------------------------------------
+// Shadow Frame
+//----------------------------------------------------------------------------
+
+// void art_portable_alloca_shadow_frame(int num_entry)
+_EVAL_DEF_INTRINSICS_FUNC(AllocaShadowFrame,
+                          art_portable_alloca_shadow_frame,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG1(kInt32ConstantTy))
+
+// void art_portable_set_vreg(int entry_idx, ...)
+_EVAL_DEF_INTRINSICS_FUNC(SetVReg,
+                          art_portable_set_vreg,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG2(kInt32ConstantTy, kVarArgTy))
+
+// void art_portable_pop_shadow_frame()
+_EVAL_DEF_INTRINSICS_FUNC(PopShadowFrame,
+                          art_portable_pop_shadow_frame,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG0())
+
+// void art_portable_update_dex_pc(uint32_t dex_pc)
+_EVAL_DEF_INTRINSICS_FUNC(UpdateDexPC,
+                          art_portable_update_dex_pc,
+                          kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG1(kInt32ConstantTy))
+
+//----------------------------------------------------------------------------
+// FP Comparison
+//----------------------------------------------------------------------------
+// int cmpl_float(float, float)
+_EVAL_DEF_INTRINSICS_FUNC(CmplFloat,
+                          art_portable_cmpl_float,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kFloatTy, kFloatTy))
+
+// int cmpg_float(float, float)
+_EVAL_DEF_INTRINSICS_FUNC(CmpgFloat,
+                          art_portable_cmpg_float,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kFloatTy, kFloatTy))
+
+// int cmpl_double(double, double)
+_EVAL_DEF_INTRINSICS_FUNC(CmplDouble,
+                          art_portable_cmpl_double,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kDoubleTy, kDoubleTy))
+
+// int cmpg_double(double, double)
+_EVAL_DEF_INTRINSICS_FUNC(CmpgDouble,
+                          art_portable_cmpg_double,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kDoubleTy, kDoubleTy))
+
+//----------------------------------------------------------------------------
+// Long Comparison
+//----------------------------------------------------------------------------
+// int cmp_long(long, long)
+_EVAL_DEF_INTRINSICS_FUNC(CmpLong,
+                          art_portable_cmp_long,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kInt64Ty, kInt64Ty))
+
+//----------------------------------------------------------------------------
+// Const intrinsics to assist MIR to Greenland_ir conversion.  Should not materialize
+// For simplicity, all use integer input
+//----------------------------------------------------------------------------
+// int const_int(int)
+_EVAL_DEF_INTRINSICS_FUNC(ConstInt,
+                          art_portable_const_int,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kInt32Ty))
+
+// JavaObject* const_obj(int)
+_EVAL_DEF_INTRINSICS_FUNC(ConstObj,
+                          art_portable_const_obj,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kJavaObjectTy,
+                          _EXPAND_ARG1(kInt32Ty))
+
+// long const_long(long)
+_EVAL_DEF_INTRINSICS_FUNC(ConstLong,
+                          art_portable_const_long,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt64Ty,
+                          _EXPAND_ARG1(kInt64Ty))
+
+// float const_float(int)
+_EVAL_DEF_INTRINSICS_FUNC(ConstFloat,
+                          art_portable_const_Float,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kFloatTy,
+                          _EXPAND_ARG1(kInt32Ty))
+
+// double const_double(long)
+_EVAL_DEF_INTRINSICS_FUNC(ConstDouble,
+                          art_portable_const_Double,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kDoubleTy,
+                          _EXPAND_ARG1(kInt64Ty))
+
+
+//----------------------------------------------------------------------------
+// Copy intrinsics to assist MIR to Greenland_ir conversion.  Should not materialize
+//----------------------------------------------------------------------------
+
+// void method_info(void)
+_EVAL_DEF_INTRINSICS_FUNC(MethodInfo,
+                          art_portable_method_info,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG0())
+
+// int copy_int(int)
+_EVAL_DEF_INTRINSICS_FUNC(CopyInt,
+                          art_portable_copy_int,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kInt32Ty))
+
+// JavaObject* copy_obj(obj)
+_EVAL_DEF_INTRINSICS_FUNC(CopyObj,
+                          art_portable_copy_obj,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kJavaObjectTy,
+                          _EXPAND_ARG1(kJavaObjectTy))
+
+// long copy_long(long)
+_EVAL_DEF_INTRINSICS_FUNC(CopyLong,
+                          art_portable_copy_long,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt64Ty,
+                          _EXPAND_ARG1(kInt64Ty))
+
+// float copy_float(float)
+_EVAL_DEF_INTRINSICS_FUNC(CopyFloat,
+                          art_portable_copy_Float,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kFloatTy,
+                          _EXPAND_ARG1(kFloatTy))
+
+// double copy_double(double)
+_EVAL_DEF_INTRINSICS_FUNC(CopyDouble,
+                          art_portable_copy_Double,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kDoubleTy,
+                          _EXPAND_ARG1(kDoubleTy))
+
+//----------------------------------------------------------------------------
+// Shift intrinsics.  Shift semantics for Dalvik are a bit different than
+// the llvm shift operators.  For 32-bit shifts, the shift count is constrained
+// to the range of 0..31, while for 64-bit shifts we limit to 0..63.
+// Further, the shift count for Long shifts in Dalvik is 32 bits, while
+// llvm requires a 64-bit shift count. For GBC, we represent shifts as an
+//  intrinsic to allow most efficient target-dependent lowering.
+//----------------------------------------------------------------------------
+// long shl_long(long,int)
+_EVAL_DEF_INTRINSICS_FUNC(SHLLong,
+                          art_portable_shl_long,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt64Ty,
+                          _EXPAND_ARG2(kInt64Ty,kInt32Ty))
+// long shr_long(long,int)
+_EVAL_DEF_INTRINSICS_FUNC(SHRLong,
+                          art_portable_shr_long,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt64Ty,
+                          _EXPAND_ARG2(kInt64Ty,kInt32Ty))
+// long ushr_long(long,int)
+_EVAL_DEF_INTRINSICS_FUNC(USHRLong,
+                          art_portable_ushl_long,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt64Ty,
+                          _EXPAND_ARG2(kInt64Ty,kInt32Ty))
+// int shl_int(int,int)
+_EVAL_DEF_INTRINSICS_FUNC(SHLInt,
+                          art_portable_shl_int,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kInt32Ty,kInt32Ty))
+// long shr_int(int,int)
+_EVAL_DEF_INTRINSICS_FUNC(SHRInt,
+                          art_portable_shr_int,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kInt32Ty,kInt32Ty))
+// int ushr_long(int,int)
+_EVAL_DEF_INTRINSICS_FUNC(USHRInt,
+                          art_portable_ushl_int,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG2(kInt32Ty,kInt32Ty))
+//----------------------------------------------------------------------------
+// Conversion instrinsics.  Note: these should eventually be removed.  We
+// can express these directly in bitcode, but by using intrinsics the
+// Quick compiler can be more efficient.  Some extra optimization infrastructure
+// will have to be developed to undo the bitcode verbosity when these are
+// done inline.
+//----------------------------------------------------------------------------
+// int int_to_byte(int)
+_EVAL_DEF_INTRINSICS_FUNC(IntToByte,
+                          art_portable_int_to_byte,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kInt32Ty))
+
+// int int_to_char(int)
+_EVAL_DEF_INTRINSICS_FUNC(IntToChar,
+                          art_portable_int_to_char,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kInt32Ty))
+
+// int int_to_short(int)
+_EVAL_DEF_INTRINSICS_FUNC(IntToShort,
+                          art_portable_int_to_short,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kInt32Ty,
+                          _EXPAND_ARG1(kInt32Ty))
+
+//----------------------------------------------------------------------------
+// Memory barrier
+//----------------------------------------------------------------------------
+// void constructor_barrier()
+_EVAL_DEF_INTRINSICS_FUNC(ConstructorBarrier,
+                          art_portable_constructor_barrier,
+                          kAttrReadOnly | kAttrNoThrow,
+                          kVoidTy,
+                          _EXPAND_ARG0())
+
+// Clean up all internal used macros
+#undef _EXPAND_ARG0
+#undef _EXPAND_ARG1
+#undef _EXPAND_ARG2
+#undef _EXPAND_ARG3
+#undef _EXPAND_ARG4
+#undef _EXPAND_ARG5
+
+#undef _JTYPE_OF_kInt1Ty_UNDER_kArray
+#undef _JTYPE_OF_kInt8Ty_UNDER_kArray
+#undef _JTYPE_OF_kInt16Ty_UNDER_kArray
+#undef _JTYPE_OF_kInt32Ty_UNDER_kArray
+#undef _JTYPE_OF_kInt64Ty_UNDER_kArray
+#undef _JTYPE_OF_kJavaObjectTy_UNDER_kArray
+
+#undef _JTYPE_OF_kInt1Ty_UNDER_kField
+#undef _JTYPE_OF_kInt8Ty_UNDER_kField
+#undef _JTYPE_OF_kInt16Ty_UNDER_kField
+#undef _JTYPE_OF_kInt32Ty_UNDER_kField
+#undef _JTYPE_OF_kInt64Ty_UNDER_kField
+#undef _JTYPE_OF_kJavaObjectTy_UNDER_kField
+
+#undef DEF_INTRINSICS_FUNC
diff --git a/compiler/llvm/intrinsic_helper.cc b/compiler/llvm/intrinsic_helper.cc
new file mode 100644
index 0000000..a34cb33
--- /dev/null
+++ b/compiler/llvm/intrinsic_helper.cc
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ */
+
+#include "intrinsic_helper.h"
+
+#include "ir_builder.h"
+
+#include <llvm/IR/Attributes.h>
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/IRBuilder.h>
+#include <llvm/IR/Intrinsics.h>
+
+namespace art {
+namespace llvm {
+
+const IntrinsicHelper::IntrinsicInfo IntrinsicHelper::Info[] = {
+#define DEF_INTRINSICS_FUNC(_, NAME, ATTR, RET_TYPE, ARG1_TYPE, ARG2_TYPE, \
+                                                     ARG3_TYPE, ARG4_TYPE, \
+                                                     ARG5_TYPE) \
+  { #NAME, ATTR, RET_TYPE, { ARG1_TYPE, ARG2_TYPE, \
+                             ARG3_TYPE, ARG4_TYPE, \
+                             ARG5_TYPE} },
+#include "intrinsic_func_list.def"
+};
+
+static ::llvm::Type* GetLLVMTypeOfIntrinsicValType(IRBuilder& irb,
+                                                   IntrinsicHelper::IntrinsicValType type) {
+  switch (type) {
+    case IntrinsicHelper::kVoidTy: {
+      return irb.getVoidTy();
+    }
+    case IntrinsicHelper::kJavaObjectTy: {
+      return irb.getJObjectTy();
+    }
+    case IntrinsicHelper::kJavaMethodTy: {
+      return irb.getJMethodTy();
+    }
+    case IntrinsicHelper::kJavaThreadTy: {
+      return irb.getJThreadTy();
+    }
+    case IntrinsicHelper::kInt1Ty:
+    case IntrinsicHelper::kInt1ConstantTy: {
+      return irb.getInt1Ty();
+    }
+    case IntrinsicHelper::kInt8Ty:
+    case IntrinsicHelper::kInt8ConstantTy: {
+      return irb.getInt8Ty();
+    }
+    case IntrinsicHelper::kInt16Ty:
+    case IntrinsicHelper::kInt16ConstantTy: {
+      return irb.getInt16Ty();
+    }
+    case IntrinsicHelper::kInt32Ty:
+    case IntrinsicHelper::kInt32ConstantTy: {
+      return irb.getInt32Ty();
+    }
+    case IntrinsicHelper::kInt64Ty:
+    case IntrinsicHelper::kInt64ConstantTy: {
+      return irb.getInt64Ty();
+    }
+    case IntrinsicHelper::kFloatTy:
+    case IntrinsicHelper::kFloatConstantTy: {
+      return irb.getFloatTy();
+    }
+    case IntrinsicHelper::kDoubleTy:
+    case IntrinsicHelper::kDoubleConstantTy: {
+      return irb.getDoubleTy();
+    }
+    case IntrinsicHelper::kNone:
+    case IntrinsicHelper::kVarArgTy:
+    default: {
+      LOG(FATAL) << "Invalid intrinsic type " << type << "to get LLVM type!";
+      return NULL;
+    }
+  }
+  // unreachable
+}
+
+IntrinsicHelper::IntrinsicHelper(::llvm::LLVMContext& context,
+                                 ::llvm::Module& module) {
+  IRBuilder irb(context, module, *this);
+
+  ::memset(intrinsic_funcs_, 0, sizeof(intrinsic_funcs_));
+
+  // This loop does the following things:
+  // 1. Introduce the intrinsic function into the module
+  // 2. Add "nocapture" and "noalias" attribute to the arguments in all
+  //    intrinsics functions.
+  // 3. Initialize intrinsic_funcs_map_.
+  for (unsigned i = 0; i < MaxIntrinsicId; i++) {
+    IntrinsicId id = static_cast<IntrinsicId>(i);
+    const IntrinsicInfo& info = Info[i];
+
+    // Parse and construct the argument type from IntrinsicInfo
+    ::llvm::Type* arg_type[kIntrinsicMaxArgc];
+    unsigned num_args = 0;
+    bool is_var_arg = false;
+    for (unsigned arg_iter = 0; arg_iter < kIntrinsicMaxArgc; arg_iter++) {
+      IntrinsicValType type = info.arg_type_[arg_iter];
+
+      if (type == kNone) {
+        break;
+      } else if (type == kVarArgTy) {
+        // Variable argument type must be the last argument
+        is_var_arg = true;
+        break;
+      }
+
+      arg_type[num_args++] = GetLLVMTypeOfIntrinsicValType(irb, type);
+    }
+
+    // Construct the function type
+    ::llvm::Type* ret_type =
+        GetLLVMTypeOfIntrinsicValType(irb, info.ret_val_type_);
+
+    ::llvm::FunctionType* type =
+        ::llvm::FunctionType::get(ret_type,
+                                  ::llvm::ArrayRef< ::llvm::Type*>(arg_type, num_args),
+                                  is_var_arg);
+
+    // Declare the function
+    ::llvm::Function *fn = ::llvm::Function::Create(type,
+                                                    ::llvm::Function::ExternalLinkage,
+                                                     info.name_, &module);
+
+    if (info.attr_ & kAttrReadOnly) {
+        fn->setOnlyReadsMemory();
+    }
+    if (info.attr_ & kAttrReadNone) {
+        fn->setDoesNotAccessMemory();
+    }
+    // None of the intrinsics throws exception
+    fn->setDoesNotThrow();
+
+    intrinsic_funcs_[id] = fn;
+
+    DCHECK_NE(fn, static_cast< ::llvm::Function*>(NULL)) << "Intrinsic `"
+        << GetName(id) << "' was not defined!";
+
+    // Add "noalias" and "nocapture" attribute to all arguments of pointer type
+    for (::llvm::Function::arg_iterator arg_iter = fn->arg_begin(),
+            arg_end = fn->arg_end(); arg_iter != arg_end; arg_iter++) {
+      if (arg_iter->getType()->isPointerTy()) {
+        std::vector< ::llvm::Attribute::AttrKind> attributes;
+        attributes.push_back(::llvm::Attribute::NoCapture);
+        attributes.push_back(::llvm::Attribute::NoAlias);
+        ::llvm::AttributeSet attribute_set = ::llvm::AttributeSet::get(fn->getContext(),
+                                                                       arg_iter->getArgNo(),
+                                                                       attributes);
+        arg_iter->addAttr(attribute_set);
+      }
+    }
+
+    // Insert the newly created intrinsic to intrinsic_funcs_map_
+    if (!intrinsic_funcs_map_.insert(std::make_pair(fn, id)).second) {
+      LOG(FATAL) << "Duplicate entry in intrinsic functions map?";
+    }
+  }
+
+  return;
+}
+
+} // namespace llvm
+} // namespace art
diff --git a/compiler/llvm/intrinsic_helper.h b/compiler/llvm/intrinsic_helper.h
new file mode 100644
index 0000000..49b8a95
--- /dev/null
+++ b/compiler/llvm/intrinsic_helper.h
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_SRC_GREENLAND_INTRINSIC_HELPER_H_
+#define ART_SRC_GREENLAND_INTRINSIC_HELPER_H_
+
+#include "base/logging.h"
+
+#include <llvm/ADT/DenseMap.h>
+
+namespace llvm {
+  class Function;
+  class FunctionType;
+  class LLVMContext;
+  class Module;
+}  // namespace llvm
+
+namespace art {
+namespace llvm {
+
+class IRBuilder;
+
+class IntrinsicHelper {
+ public:
+  enum IntrinsicId {
+#define DEF_INTRINSICS_FUNC(ID, ...) ID,
+#include "intrinsic_func_list.def"
+    MaxIntrinsicId,
+
+    // Pseudo-intrinsics Id
+    UnknownId
+  };
+
+  enum IntrinsicAttribute {
+    kAttrNone     = 0,
+
+    // Intrinsic that neither modified the memory state nor refer to the global
+    // state
+    kAttrReadNone = 1 << 0,
+
+    // Intrinsic that doesn't modify the memory state. Note that one should set
+    // this flag carefully when the intrinsic may throw exception. Since the
+    // thread state is implicitly modified when an exception is thrown.
+    kAttrReadOnly = 1 << 1,
+
+    // Note that intrinsic without kAttrNoThrow and kAttrDoThrow set means that
+    // intrinsic generates exception in some cases
+
+    // Intrinsic that never generates exception
+    kAttrNoThrow  = 1 << 2,
+    // Intrinsic that always generate exception
+    kAttrDoThrow  = 1 << 3,
+  };
+
+  enum IntrinsicValType {
+    kNone,
+
+    kVoidTy,
+
+    kJavaObjectTy,
+    kJavaMethodTy,
+    kJavaThreadTy,
+
+    kInt1Ty,
+    kInt8Ty,
+    kInt16Ty,
+    kInt32Ty,
+    kInt64Ty,
+    kFloatTy,
+    kDoubleTy,
+
+    kInt1ConstantTy,
+    kInt8ConstantTy,
+    kInt16ConstantTy,
+    kInt32ConstantTy,
+    kInt64ConstantTy,
+    kFloatConstantTy,
+    kDoubleConstantTy,
+
+    kVarArgTy,
+  };
+
+  enum {
+    kIntrinsicMaxArgc = 5
+  };
+
+  typedef struct IntrinsicInfo {
+    const char* name_;
+    unsigned attr_;
+    IntrinsicValType ret_val_type_;
+    IntrinsicValType arg_type_[kIntrinsicMaxArgc];
+  } IntrinsicInfo;
+
+ private:
+  static const IntrinsicInfo Info[];
+
+ public:
+  static const IntrinsicInfo& GetInfo(IntrinsicId id) {
+    DCHECK(id >= 0 && id < MaxIntrinsicId) << "Unknown ART intrinsics ID: "
+                                           << id;
+    return Info[id];
+  }
+
+  static const char* GetName(IntrinsicId id) {
+    return (id <= MaxIntrinsicId) ? GetInfo(id).name_ : "InvalidIntrinsic";
+  }
+
+  static unsigned GetAttr(IntrinsicId id) {
+    return GetInfo(id).attr_;
+  }
+
+ public:
+  IntrinsicHelper(::llvm::LLVMContext& context, ::llvm::Module& module);
+
+  ::llvm::Function* GetIntrinsicFunction(IntrinsicId id) {
+    DCHECK(id >= 0 && id < MaxIntrinsicId) << "Unknown ART intrinsics ID: "
+                                           << id;
+    return intrinsic_funcs_[id];
+  }
+
+  IntrinsicId GetIntrinsicId(const ::llvm::Function* func) const {
+    ::llvm::DenseMap<const ::llvm::Function*, IntrinsicId>::const_iterator
+        i = intrinsic_funcs_map_.find(func);
+    if (i == intrinsic_funcs_map_.end()) {
+      return UnknownId;
+    } else {
+      return i->second;
+    }
+  }
+
+ private:
+  // FIXME: "+1" is to workaround the GCC bugs:
+  // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
+  // Remove this when uses newer GCC (> 4.4.3)
+  ::llvm::Function* intrinsic_funcs_[MaxIntrinsicId + 1];
+
+  // Map a llvm::Function to its intrinsic id
+  ::llvm::DenseMap<const ::llvm::Function*, IntrinsicId> intrinsic_funcs_map_;
+};
+
+} // namespace llvm
+} // namespace art
+
+#endif // ART_SRC_GREENLAND_INTRINSIC_HELPER_H_
diff --git a/compiler/llvm/ir_builder.cc b/compiler/llvm/ir_builder.cc
new file mode 100644
index 0000000..a65cf2b
--- /dev/null
+++ b/compiler/llvm/ir_builder.cc
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+#include "ir_builder.h"
+
+#include "base/stringprintf.h"
+
+#include <llvm/IR/Module.h>
+
+namespace art {
+namespace llvm {
+
+
+//----------------------------------------------------------------------------
+// General
+//----------------------------------------------------------------------------
+
+IRBuilder::IRBuilder(::llvm::LLVMContext& context, ::llvm::Module& module,
+                     IntrinsicHelper& intrinsic_helper)
+    : LLVMIRBuilder(context), module_(&module), mdb_(context), java_object_type_(NULL),
+      java_method_type_(NULL), java_thread_type_(NULL), intrinsic_helper_(intrinsic_helper) {
+  // Get java object type from module
+  ::llvm::Type* jobject_struct_type = module.getTypeByName("JavaObject");
+  CHECK(jobject_struct_type != NULL);
+  java_object_type_ = jobject_struct_type->getPointerTo();
+
+  // If type of Method is not explicitly defined in the module, use JavaObject*
+  ::llvm::Type* type = module.getTypeByName("Method");
+  if (type != NULL) {
+    java_method_type_ = type->getPointerTo();
+  } else {
+    java_method_type_ = java_object_type_;
+  }
+
+  // If type of Thread is not explicitly defined in the module, use JavaObject*
+  type = module.getTypeByName("Thread");
+  if (type != NULL) {
+    java_thread_type_ = type->getPointerTo();
+  } else {
+    java_thread_type_ = java_object_type_;
+  }
+
+  // Create JEnv* type
+  ::llvm::Type* jenv_struct_type = ::llvm::StructType::create(context, "JEnv");
+  jenv_type_ = jenv_struct_type->getPointerTo();
+
+  // Get Art shadow frame struct type from module
+  art_frame_type_ = module.getTypeByName("ShadowFrame");
+  CHECK(art_frame_type_ != NULL);
+
+  runtime_support_ = NULL;
+}
+
+
+//----------------------------------------------------------------------------
+// Type Helper Function
+//----------------------------------------------------------------------------
+
+::llvm::Type* IRBuilder::getJType(JType jty) {
+  switch (jty) {
+  case kVoid:
+    return getJVoidTy();
+
+  case kBoolean:
+    return getJBooleanTy();
+
+  case kByte:
+    return getJByteTy();
+
+  case kChar:
+    return getJCharTy();
+
+  case kShort:
+    return getJShortTy();
+
+  case kInt:
+    return getJIntTy();
+
+  case kLong:
+    return getJLongTy();
+
+  case kFloat:
+    return getJFloatTy();
+
+  case kDouble:
+    return getJDoubleTy();
+
+  case kObject:
+    return getJObjectTy();
+
+  default:
+    LOG(FATAL) << "Unknown java type: " << jty;
+    return NULL;
+  }
+}
+
+::llvm::StructType* IRBuilder::getShadowFrameTy(uint32_t vreg_size) {
+  std::string name(StringPrintf("ShadowFrame%u", vreg_size));
+
+  // Try to find the existing struct type definition
+  if (::llvm::Type* type = module_->getTypeByName(name)) {
+    CHECK(::llvm::isa< ::llvm::StructType>(type));
+    return static_cast< ::llvm::StructType*>(type);
+  }
+
+  // Create new struct type definition
+  ::llvm::Type* elem_types[] = {
+    art_frame_type_,
+    ::llvm::ArrayType::get(getInt32Ty(), vreg_size),
+  };
+
+  return ::llvm::StructType::create(elem_types, name);
+}
+
+
+} // namespace llvm
+} // namespace art
diff --git a/compiler/llvm/ir_builder.h b/compiler/llvm/ir_builder.h
new file mode 100644
index 0000000..734b22f
--- /dev/null
+++ b/compiler/llvm/ir_builder.h
@@ -0,0 +1,490 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_SRC_COMPILER_LLVM_IR_BUILDER_H_
+#define ART_SRC_COMPILER_LLVM_IR_BUILDER_H_
+
+#include "backend_types.h"
+#include "dex/compiler_enums.h"
+#include "intrinsic_helper.h"
+#include "md_builder.h"
+#include "runtime_support_builder.h"
+#include "runtime_support_llvm_func.h"
+
+#include <llvm/IR/Constants.h>
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/IRBuilder.h>
+#include <llvm/IR/LLVMContext.h>
+#include <llvm/IR/Type.h>
+#include <llvm/Support/NoFolder.h>
+
+#include <stdint.h>
+
+
+namespace art {
+namespace llvm {
+
+class InserterWithDexOffset : public ::llvm::IRBuilderDefaultInserter<true> {
+  public:
+    InserterWithDexOffset() : node_(NULL) {}
+
+    void InsertHelper(::llvm::Instruction *I, const ::llvm::Twine &Name,
+                      ::llvm::BasicBlock *BB,
+                      ::llvm::BasicBlock::iterator InsertPt) const {
+      ::llvm::IRBuilderDefaultInserter<true>::InsertHelper(I, Name, BB, InsertPt);
+      if (node_ != NULL) {
+        I->setMetadata("DexOff", node_);
+      }
+    }
+
+    void SetDexOffset(::llvm::MDNode* node) {
+      node_ = node;
+    }
+  private:
+    ::llvm::MDNode* node_;
+};
+
+typedef ::llvm::IRBuilder<true, ::llvm::ConstantFolder, InserterWithDexOffset> LLVMIRBuilder;
+// NOTE: Here we define our own LLVMIRBuilder type alias, so that we can
+// switch "preserveNames" template parameter easily.
+
+
+class IRBuilder : public LLVMIRBuilder {
+ public:
+  //--------------------------------------------------------------------------
+  // General
+  //--------------------------------------------------------------------------
+
+  IRBuilder(::llvm::LLVMContext& context, ::llvm::Module& module,
+            IntrinsicHelper& intrinsic_helper);
+
+
+  //--------------------------------------------------------------------------
+  // Extend load & store for TBAA
+  //--------------------------------------------------------------------------
+
+  ::llvm::LoadInst* CreateLoad(::llvm::Value* ptr, ::llvm::MDNode* tbaa_info) {
+    ::llvm::LoadInst* inst = LLVMIRBuilder::CreateLoad(ptr);
+    inst->setMetadata(::llvm::LLVMContext::MD_tbaa, tbaa_info);
+    return inst;
+  }
+
+  ::llvm::StoreInst* CreateStore(::llvm::Value* val, ::llvm::Value* ptr, ::llvm::MDNode* tbaa_info) {
+    ::llvm::StoreInst* inst = LLVMIRBuilder::CreateStore(val, ptr);
+    inst->setMetadata(::llvm::LLVMContext::MD_tbaa, tbaa_info);
+    return inst;
+  }
+
+  ::llvm::AtomicCmpXchgInst*
+  CreateAtomicCmpXchgInst(::llvm::Value* ptr, ::llvm::Value* cmp, ::llvm::Value* val,
+                          ::llvm::MDNode* tbaa_info) {
+    ::llvm::AtomicCmpXchgInst* inst =
+        LLVMIRBuilder::CreateAtomicCmpXchg(ptr, cmp, val, ::llvm::Acquire);
+    inst->setMetadata(::llvm::LLVMContext::MD_tbaa, tbaa_info);
+    return inst;
+  }
+
+  //--------------------------------------------------------------------------
+  // Extend memory barrier
+  //--------------------------------------------------------------------------
+  void CreateMemoryBarrier(MemBarrierKind barrier_kind) {
+#if ANDROID_SMP
+    // TODO: select atomic ordering according to given barrier kind.
+    CreateFence(::llvm::SequentiallyConsistent);
+#endif
+  }
+
+  //--------------------------------------------------------------------------
+  // TBAA
+  //--------------------------------------------------------------------------
+
+  // TODO: After we design the non-special TBAA info, re-design the TBAA interface.
+  ::llvm::LoadInst* CreateLoad(::llvm::Value* ptr, TBAASpecialType special_ty) {
+    return CreateLoad(ptr, mdb_.GetTBAASpecialType(special_ty));
+  }
+
+  ::llvm::StoreInst* CreateStore(::llvm::Value* val, ::llvm::Value* ptr, TBAASpecialType special_ty) {
+    DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
+    return CreateStore(val, ptr, mdb_.GetTBAASpecialType(special_ty));
+  }
+
+  ::llvm::LoadInst* CreateLoad(::llvm::Value* ptr, TBAASpecialType special_ty, JType j_ty) {
+    return CreateLoad(ptr, mdb_.GetTBAAMemoryJType(special_ty, j_ty));
+  }
+
+  ::llvm::StoreInst* CreateStore(::llvm::Value* val, ::llvm::Value* ptr,
+                               TBAASpecialType special_ty, JType j_ty) {
+    DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
+    return CreateStore(val, ptr, mdb_.GetTBAAMemoryJType(special_ty, j_ty));
+  }
+
+  ::llvm::LoadInst* LoadFromObjectOffset(::llvm::Value* object_addr,
+                                       int64_t offset,
+                                       ::llvm::Type* type,
+                                       TBAASpecialType special_ty) {
+    return LoadFromObjectOffset(object_addr, offset, type, mdb_.GetTBAASpecialType(special_ty));
+  }
+
+  void StoreToObjectOffset(::llvm::Value* object_addr,
+                           int64_t offset,
+                           ::llvm::Value* new_value,
+                           TBAASpecialType special_ty) {
+    DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
+    StoreToObjectOffset(object_addr, offset, new_value, mdb_.GetTBAASpecialType(special_ty));
+  }
+
+  ::llvm::LoadInst* LoadFromObjectOffset(::llvm::Value* object_addr,
+                                       int64_t offset,
+                                       ::llvm::Type* type,
+                                       TBAASpecialType special_ty, JType j_ty) {
+    return LoadFromObjectOffset(object_addr, offset, type, mdb_.GetTBAAMemoryJType(special_ty, j_ty));
+  }
+
+  void StoreToObjectOffset(::llvm::Value* object_addr,
+                           int64_t offset,
+                           ::llvm::Value* new_value,
+                           TBAASpecialType special_ty, JType j_ty) {
+    DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
+    StoreToObjectOffset(object_addr, offset, new_value, mdb_.GetTBAAMemoryJType(special_ty, j_ty));
+  }
+
+  ::llvm::AtomicCmpXchgInst*
+  CompareExchangeObjectOffset(::llvm::Value* object_addr,
+                              int64_t offset,
+                              ::llvm::Value* cmp_value,
+                              ::llvm::Value* new_value,
+                              TBAASpecialType special_ty) {
+    DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
+    return CompareExchangeObjectOffset(object_addr, offset, cmp_value, new_value,
+                                       mdb_.GetTBAASpecialType(special_ty));
+  }
+
+  void SetTBAA(::llvm::Instruction* inst, TBAASpecialType special_ty) {
+    inst->setMetadata(::llvm::LLVMContext::MD_tbaa, mdb_.GetTBAASpecialType(special_ty));
+  }
+
+
+  //--------------------------------------------------------------------------
+  // Static Branch Prediction
+  //--------------------------------------------------------------------------
+
+  // Import the orignal conditional branch
+  using LLVMIRBuilder::CreateCondBr;
+  ::llvm::BranchInst* CreateCondBr(::llvm::Value *cond,
+                                 ::llvm::BasicBlock* true_bb,
+                                 ::llvm::BasicBlock* false_bb,
+                                 ExpectCond expect) {
+    ::llvm::BranchInst* branch_inst = CreateCondBr(cond, true_bb, false_bb);
+    if (false) {
+      // TODO: http://b/8511695 Restore branch weight metadata
+      branch_inst->setMetadata(::llvm::LLVMContext::MD_prof, mdb_.GetBranchWeights(expect));
+    }
+    return branch_inst;
+  }
+
+
+  //--------------------------------------------------------------------------
+  // Pointer Arithmetic Helper Function
+  //--------------------------------------------------------------------------
+
+  ::llvm::IntegerType* getPtrEquivIntTy() {
+    return getInt32Ty();
+  }
+
+  size_t getSizeOfPtrEquivInt() {
+    return 4;
+  }
+
+  ::llvm::ConstantInt* getSizeOfPtrEquivIntValue() {
+    return getPtrEquivInt(getSizeOfPtrEquivInt());
+  }
+
+  ::llvm::ConstantInt* getPtrEquivInt(int64_t i) {
+    return ::llvm::ConstantInt::get(getPtrEquivIntTy(), i);
+  }
+
+  ::llvm::Value* CreatePtrDisp(::llvm::Value* base,
+                             ::llvm::Value* offset,
+                             ::llvm::PointerType* ret_ty) {
+
+    ::llvm::Value* base_int = CreatePtrToInt(base, getPtrEquivIntTy());
+    ::llvm::Value* result_int = CreateAdd(base_int, offset);
+    ::llvm::Value* result = CreateIntToPtr(result_int, ret_ty);
+
+    return result;
+  }
+
+  ::llvm::Value* CreatePtrDisp(::llvm::Value* base,
+                             ::llvm::Value* bs,
+                             ::llvm::Value* count,
+                             ::llvm::Value* offset,
+                             ::llvm::PointerType* ret_ty) {
+
+    ::llvm::Value* block_offset = CreateMul(bs, count);
+    ::llvm::Value* total_offset = CreateAdd(block_offset, offset);
+
+    return CreatePtrDisp(base, total_offset, ret_ty);
+  }
+
+  ::llvm::LoadInst* LoadFromObjectOffset(::llvm::Value* object_addr,
+                                       int64_t offset,
+                                       ::llvm::Type* type,
+                                       ::llvm::MDNode* tbaa_info) {
+    // Convert offset to ::llvm::value
+    ::llvm::Value* llvm_offset = getPtrEquivInt(offset);
+    // Calculate the value's address
+    ::llvm::Value* value_addr = CreatePtrDisp(object_addr, llvm_offset, type->getPointerTo());
+    // Load
+    return CreateLoad(value_addr, tbaa_info);
+  }
+
+  void StoreToObjectOffset(::llvm::Value* object_addr,
+                           int64_t offset,
+                           ::llvm::Value* new_value,
+                           ::llvm::MDNode* tbaa_info) {
+    // Convert offset to ::llvm::value
+    ::llvm::Value* llvm_offset = getPtrEquivInt(offset);
+    // Calculate the value's address
+    ::llvm::Value* value_addr = CreatePtrDisp(object_addr,
+                                            llvm_offset,
+                                            new_value->getType()->getPointerTo());
+    // Store
+    CreateStore(new_value, value_addr, tbaa_info);
+  }
+
+  ::llvm::AtomicCmpXchgInst* CompareExchangeObjectOffset(::llvm::Value* object_addr,
+                                                       int64_t offset,
+                                                       ::llvm::Value* cmp_value,
+                                                       ::llvm::Value* new_value,
+                                                       ::llvm::MDNode* tbaa_info) {
+    // Convert offset to ::llvm::value
+    ::llvm::Value* llvm_offset = getPtrEquivInt(offset);
+    // Calculate the value's address
+    ::llvm::Value* value_addr = CreatePtrDisp(object_addr,
+                                            llvm_offset,
+                                            new_value->getType()->getPointerTo());
+    // Atomic compare and exchange
+    return CreateAtomicCmpXchgInst(value_addr, cmp_value, new_value, tbaa_info);
+  }
+
+
+  //--------------------------------------------------------------------------
+  // Runtime Helper Function
+  //--------------------------------------------------------------------------
+
+  RuntimeSupportBuilder& Runtime() {
+    return *runtime_support_;
+  }
+
+  // TODO: Deprecate
+  ::llvm::Function* GetRuntime(runtime_support::RuntimeId rt) {
+    return runtime_support_->GetRuntimeSupportFunction(rt);
+  }
+
+  // TODO: Deprecate
+  void SetRuntimeSupport(RuntimeSupportBuilder* runtime_support) {
+    // Can only set once. We can't do this on constructor, because RuntimeSupportBuilder needs
+    // IRBuilder.
+    if (runtime_support_ == NULL && runtime_support != NULL) {
+      runtime_support_ = runtime_support;
+    }
+  }
+
+
+  //--------------------------------------------------------------------------
+  // Type Helper Function
+  //--------------------------------------------------------------------------
+
+  ::llvm::Type* getJType(char shorty_jty) {
+    return getJType(GetJTypeFromShorty(shorty_jty));
+  }
+
+  ::llvm::Type* getJType(JType jty);
+
+  ::llvm::Type* getJVoidTy() {
+    return getVoidTy();
+  }
+
+  ::llvm::IntegerType* getJBooleanTy() {
+    return getInt8Ty();
+  }
+
+  ::llvm::IntegerType* getJByteTy() {
+    return getInt8Ty();
+  }
+
+  ::llvm::IntegerType* getJCharTy() {
+    return getInt16Ty();
+  }
+
+  ::llvm::IntegerType* getJShortTy() {
+    return getInt16Ty();
+  }
+
+  ::llvm::IntegerType* getJIntTy() {
+    return getInt32Ty();
+  }
+
+  ::llvm::IntegerType* getJLongTy() {
+    return getInt64Ty();
+  }
+
+  ::llvm::Type* getJFloatTy() {
+    return getFloatTy();
+  }
+
+  ::llvm::Type* getJDoubleTy() {
+    return getDoubleTy();
+  }
+
+  ::llvm::PointerType* getJObjectTy() {
+    return java_object_type_;
+  }
+
+  ::llvm::PointerType* getJMethodTy() {
+    return java_method_type_;
+  }
+
+  ::llvm::PointerType* getJThreadTy() {
+    return java_thread_type_;
+  }
+
+  ::llvm::Type* getArtFrameTy() {
+    return art_frame_type_;
+  }
+
+  ::llvm::PointerType* getJEnvTy() {
+    return jenv_type_;
+  }
+
+  ::llvm::Type* getJValueTy() {
+    // NOTE: JValue is an union type, which may contains boolean, byte, char,
+    // short, int, long, float, double, Object.  However, LLVM itself does
+    // not support union type, so we have to return a type with biggest size,
+    // then bitcast it before we use it.
+    return getJLongTy();
+  }
+
+  ::llvm::StructType* getShadowFrameTy(uint32_t vreg_size);
+
+
+  //--------------------------------------------------------------------------
+  // Constant Value Helper Function
+  //--------------------------------------------------------------------------
+
+  ::llvm::ConstantInt* getJBoolean(bool is_true) {
+    return (is_true) ? getTrue() : getFalse();
+  }
+
+  ::llvm::ConstantInt* getJByte(int8_t i) {
+    return ::llvm::ConstantInt::getSigned(getJByteTy(), i);
+  }
+
+  ::llvm::ConstantInt* getJChar(int16_t i) {
+    return ::llvm::ConstantInt::getSigned(getJCharTy(), i);
+  }
+
+  ::llvm::ConstantInt* getJShort(int16_t i) {
+    return ::llvm::ConstantInt::getSigned(getJShortTy(), i);
+  }
+
+  ::llvm::ConstantInt* getJInt(int32_t i) {
+    return ::llvm::ConstantInt::getSigned(getJIntTy(), i);
+  }
+
+  ::llvm::ConstantInt* getJLong(int64_t i) {
+    return ::llvm::ConstantInt::getSigned(getJLongTy(), i);
+  }
+
+  ::llvm::Constant* getJFloat(float f) {
+    return ::llvm::ConstantFP::get(getJFloatTy(), f);
+  }
+
+  ::llvm::Constant* getJDouble(double d) {
+    return ::llvm::ConstantFP::get(getJDoubleTy(), d);
+  }
+
+  ::llvm::ConstantPointerNull* getJNull() {
+    return ::llvm::ConstantPointerNull::get(getJObjectTy());
+  }
+
+  ::llvm::Constant* getJZero(char shorty_jty) {
+    return getJZero(GetJTypeFromShorty(shorty_jty));
+  }
+
+  ::llvm::Constant* getJZero(JType jty) {
+    switch (jty) {
+    case kVoid:
+      LOG(FATAL) << "Zero is not a value of void type";
+      return NULL;
+
+    case kBoolean:
+      return getJBoolean(false);
+
+    case kByte:
+      return getJByte(0);
+
+    case kChar:
+      return getJChar(0);
+
+    case kShort:
+      return getJShort(0);
+
+    case kInt:
+      return getJInt(0);
+
+    case kLong:
+      return getJLong(0);
+
+    case kFloat:
+      return getJFloat(0.0f);
+
+    case kDouble:
+      return getJDouble(0.0);
+
+    case kObject:
+      return getJNull();
+
+    default:
+      LOG(FATAL) << "Unknown java type: " << jty;
+      return NULL;
+    }
+  }
+
+
+ private:
+  ::llvm::Module* module_;
+
+  MDBuilder mdb_;
+
+  ::llvm::PointerType* java_object_type_;
+  ::llvm::PointerType* java_method_type_;
+  ::llvm::PointerType* java_thread_type_;
+
+  ::llvm::PointerType* jenv_type_;
+
+  ::llvm::StructType* art_frame_type_;
+
+  RuntimeSupportBuilder* runtime_support_;
+
+  IntrinsicHelper& intrinsic_helper_;
+};
+
+
+} // namespace llvm
+} // namespace art
+
+#endif // ART_SRC_COMPILER_LLVM_IR_BUILDER_H_
diff --git a/compiler/llvm/llvm_compilation_unit.cc b/compiler/llvm/llvm_compilation_unit.cc
new file mode 100644
index 0000000..dfb5724
--- /dev/null
+++ b/compiler/llvm/llvm_compilation_unit.cc
@@ -0,0 +1,343 @@
+/*
+ * 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.
+ */
+
+// TODO: TargetLibraryInfo is included before sys/... because on Android bionic does #define tricks like:
+//
+// #define  stat64    stat
+// #define  fstat64   fstat
+// #define  lstat64   lstat
+// 
+// which causes grief. bionic probably should not do that.
+#include <llvm/Target/TargetLibraryInfo.h>
+
+#include "llvm_compilation_unit.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <string>
+
+#include <llvm/ADT/OwningPtr.h>
+#include <llvm/ADT/StringSet.h>
+#include <llvm/ADT/Triple.h>
+#include <llvm/Analysis/CallGraph.h>
+#include <llvm/Analysis/CallGraphSCCPass.h>
+#include <llvm/Analysis/Dominators.h>
+#include <llvm/Analysis/LoopInfo.h>
+#include <llvm/Analysis/LoopPass.h>
+#include <llvm/Analysis/RegionPass.h>
+#include <llvm/Analysis/ScalarEvolution.h>
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/Assembly/PrintModulePass.h>
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/CodeGen/MachineFrameInfo.h>
+#include <llvm/CodeGen/MachineFunction.h>
+#include <llvm/CodeGen/MachineFunctionPass.h>
+#include <llvm/DebugInfo.h>
+#include <llvm/IR/DataLayout.h>
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/LLVMContext.h>
+#include <llvm/IR/Module.h>
+#include <llvm/Object/ObjectFile.h>
+#include <llvm/PassManager.h>
+#include <llvm/Support/Debug.h>
+#include <llvm/Support/ELF.h>
+#include <llvm/Support/FormattedStream.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include <llvm/Support/PassNameParser.h>
+#include <llvm/Support/PluginLoader.h>
+#include <llvm/Support/PrettyStackTrace.h>
+#include <llvm/Support/Signals.h>
+#include <llvm/Support/SystemUtils.h>
+#include <llvm/Support/TargetRegistry.h>
+#include <llvm/Support/TargetSelect.h>
+#include <llvm/Support/ToolOutputFile.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/system_error.h>
+#include <llvm/Target/TargetMachine.h>
+#include <llvm/Transforms/IPO.h>
+#include <llvm/Transforms/IPO/PassManagerBuilder.h>
+#include <llvm/Transforms/Scalar.h>
+
+#include "base/logging.h"
+#include "base/unix_file/fd_file.h"
+#include "compiled_method.h"
+#include "compiler_llvm.h"
+#include "instruction_set.h"
+#include "ir_builder.h"
+#include "os.h"
+#include "runtime_support_builder_arm.h"
+#include "runtime_support_builder_thumb2.h"
+#include "runtime_support_builder_x86.h"
+#include "utils_llvm.h"
+
+namespace art {
+namespace llvm {
+
+::llvm::FunctionPass*
+CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
+                      CompilerDriver* compiler, const DexCompilationUnit* dex_compilation_unit);
+
+::llvm::Module* makeLLVMModuleContents(::llvm::Module* module);
+
+
+LlvmCompilationUnit::LlvmCompilationUnit(const CompilerLLVM* compiler_llvm, size_t cunit_id)
+    : compiler_llvm_(compiler_llvm), cunit_id_(cunit_id) {
+  driver_ = NULL;
+  dex_compilation_unit_ = NULL;
+  llvm_info_.reset(new LLVMInfo());
+  context_.reset(llvm_info_->GetLLVMContext());
+  module_ = llvm_info_->GetLLVMModule();
+
+  // Include the runtime function declaration
+  makeLLVMModuleContents(module_);
+
+
+  intrinsic_helper_.reset(new IntrinsicHelper(*context_, *module_));
+
+  // Create IRBuilder
+  irb_.reset(new IRBuilder(*context_, *module_, *intrinsic_helper_));
+
+  // We always need a switch case, so just use a normal function.
+  switch(GetInstructionSet()) {
+  default:
+    runtime_support_.reset(new RuntimeSupportBuilder(*context_, *module_, *irb_));
+    break;
+  case kArm:
+    runtime_support_.reset(new RuntimeSupportBuilderARM(*context_, *module_, *irb_));
+    break;
+  case kThumb2:
+    runtime_support_.reset(new RuntimeSupportBuilderThumb2(*context_, *module_, *irb_));
+    break;
+  case kX86:
+    runtime_support_.reset(new RuntimeSupportBuilderX86(*context_, *module_, *irb_));
+    break;
+  }
+
+  irb_->SetRuntimeSupport(runtime_support_.get());
+}
+
+
+LlvmCompilationUnit::~LlvmCompilationUnit() {
+  ::llvm::LLVMContext* llvm_context = context_.release(); // Managed by llvm_info_
+  CHECK(llvm_context != NULL);
+}
+
+
+InstructionSet LlvmCompilationUnit::GetInstructionSet() const {
+  return compiler_llvm_->GetInstructionSet();
+}
+
+
+static std::string DumpDirectory() {
+  if (kIsTargetBuild) {
+    return GetDalvikCacheOrDie(GetAndroidData());
+  }
+  return "/tmp";
+}
+
+void LlvmCompilationUnit::DumpBitcodeToFile() {
+  std::string bitcode;
+  DumpBitcodeToString(bitcode);
+  std::string filename(StringPrintf("%s/Art%u.bc", DumpDirectory().c_str(), cunit_id_));
+  UniquePtr<File> output(OS::OpenFile(filename.c_str(), true));
+  output->WriteFully(bitcode.data(), bitcode.size());
+  LOG(INFO) << ".bc file written successfully: " << filename;
+}
+
+void LlvmCompilationUnit::DumpBitcodeToString(std::string& str_buffer) {
+  ::llvm::raw_string_ostream str_os(str_buffer);
+  ::llvm::WriteBitcodeToFile(module_, str_os);
+}
+
+bool LlvmCompilationUnit::Materialize() {
+
+  const bool kDumpBitcode = false;
+  if (kDumpBitcode) {
+    // Dump the bitcode for debugging
+    DumpBitcodeToFile();
+  }
+
+  // Compile and prelink ::llvm::Module
+  if (!MaterializeToString(elf_object_)) {
+    LOG(ERROR) << "Failed to materialize compilation unit " << cunit_id_;
+    return false;
+  }
+
+  const bool kDumpELF = false;
+  if (kDumpELF) {
+    // Dump the ELF image for debugging
+    std::string filename(StringPrintf("%s/Art%u.o", DumpDirectory().c_str(), cunit_id_));
+    UniquePtr<File> output(OS::OpenFile(filename.c_str(), true));
+    output->WriteFully(elf_object_.data(), elf_object_.size());
+    LOG(INFO) << ".o file written successfully: " << filename;
+  }
+
+  return true;
+}
+
+
+bool LlvmCompilationUnit::MaterializeToString(std::string& str_buffer) {
+  ::llvm::raw_string_ostream str_os(str_buffer);
+  return MaterializeToRawOStream(str_os);
+}
+
+
+bool LlvmCompilationUnit::MaterializeToRawOStream(::llvm::raw_ostream& out_stream) {
+  // Lookup the LLVM target
+  std::string target_triple;
+  std::string target_cpu;
+  std::string target_attr;
+  CompilerDriver::InstructionSetToLLVMTarget(GetInstructionSet(), target_triple, target_cpu, target_attr);
+
+  std::string errmsg;
+  const ::llvm::Target* target =
+    ::llvm::TargetRegistry::lookupTarget(target_triple, errmsg);
+
+  CHECK(target != NULL) << errmsg;
+
+  // Target options
+  ::llvm::TargetOptions target_options;
+  target_options.FloatABIType = ::llvm::FloatABI::Soft;
+  target_options.NoFramePointerElim = true;
+  target_options.NoFramePointerElimNonLeaf = true;
+  target_options.UseSoftFloat = false;
+  target_options.EnableFastISel = false;
+
+  // Create the ::llvm::TargetMachine
+  ::llvm::OwningPtr< ::llvm::TargetMachine> target_machine(
+    target->createTargetMachine(target_triple, target_cpu, target_attr, target_options,
+                                ::llvm::Reloc::Static, ::llvm::CodeModel::Small,
+                                ::llvm::CodeGenOpt::Aggressive));
+
+  CHECK(target_machine.get() != NULL) << "Failed to create target machine";
+
+  // Add target data
+  const ::llvm::DataLayout* data_layout = target_machine->getDataLayout();
+
+  // PassManager for code generation passes
+  ::llvm::PassManager pm;
+  pm.add(new ::llvm::DataLayout(*data_layout));
+
+  // FunctionPassManager for optimization pass
+  ::llvm::FunctionPassManager fpm(module_);
+  fpm.add(new ::llvm::DataLayout(*data_layout));
+
+  if (bitcode_filename_.empty()) {
+    // If we don't need write the bitcode to file, add the AddSuspendCheckToLoopLatchPass to the
+    // regular FunctionPass.
+    fpm.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(),
+                                  driver_, dex_compilation_unit_));
+  } else {
+    ::llvm::FunctionPassManager fpm2(module_);
+    fpm2.add(CreateGBCExpanderPass(*llvm_info_->GetIntrinsicHelper(), *irb_.get(),
+                                   driver_, dex_compilation_unit_));
+    fpm2.doInitialization();
+    for (::llvm::Module::iterator F = module_->begin(), E = module_->end();
+         F != E; ++F) {
+      fpm2.run(*F);
+    }
+    fpm2.doFinalization();
+
+    // Write bitcode to file
+    std::string errmsg;
+
+    ::llvm::OwningPtr< ::llvm::tool_output_file> out_file(
+      new ::llvm::tool_output_file(bitcode_filename_.c_str(), errmsg,
+                                 ::llvm::raw_fd_ostream::F_Binary));
+
+
+    if (!errmsg.empty()) {
+      LOG(ERROR) << "Failed to create bitcode output file: " << errmsg;
+      return false;
+    }
+
+    ::llvm::WriteBitcodeToFile(module_, out_file->os());
+    out_file->keep();
+  }
+
+  // Add optimization pass
+  ::llvm::PassManagerBuilder pm_builder;
+  // TODO: Use inliner after we can do IPO.
+  pm_builder.Inliner = NULL;
+  //pm_builder.Inliner = ::llvm::createFunctionInliningPass();
+  //pm_builder.Inliner = ::llvm::createAlwaysInlinerPass();
+  //pm_builder.Inliner = ::llvm::createPartialInliningPass();
+  pm_builder.OptLevel = 3;
+  pm_builder.DisableSimplifyLibCalls = 1;
+  pm_builder.DisableUnitAtATime = 1;
+  pm_builder.populateFunctionPassManager(fpm);
+  pm_builder.populateModulePassManager(pm);
+  pm.add(::llvm::createStripDeadPrototypesPass());
+
+  // Add passes to emit ELF image
+  {
+    ::llvm::formatted_raw_ostream formatted_os(out_stream, false);
+
+    // Ask the target to add backend passes as necessary.
+    if (target_machine->addPassesToEmitFile(pm,
+                                            formatted_os,
+                                            ::llvm::TargetMachine::CGFT_ObjectFile,
+                                            true)) {
+      LOG(FATAL) << "Unable to generate ELF for this target";
+      return false;
+    }
+
+    // Run the per-function optimization
+    fpm.doInitialization();
+    for (::llvm::Module::iterator F = module_->begin(), E = module_->end();
+         F != E; ++F) {
+      fpm.run(*F);
+    }
+    fpm.doFinalization();
+
+    // Run the code generation passes
+    pm.run(*module_);
+  }
+
+  return true;
+}
+
+// Check whether the align is less than or equal to the code alignment of
+// that architecture.  Since the Oat writer only guarantee that the compiled
+// method being aligned to kArchAlignment, we have no way to align the ELf
+// section if the section alignment is greater than kArchAlignment.
+void LlvmCompilationUnit::CheckCodeAlign(uint32_t align) const {
+  InstructionSet insn_set = GetInstructionSet();
+  switch (insn_set) {
+  case kThumb2:
+  case kArm:
+    CHECK_LE(align, static_cast<uint32_t>(kArmAlignment));
+    break;
+
+  case kX86:
+    CHECK_LE(align, static_cast<uint32_t>(kX86Alignment));
+    break;
+
+  case kMips:
+    CHECK_LE(align, static_cast<uint32_t>(kMipsAlignment));
+    break;
+
+  default:
+    LOG(FATAL) << "Unknown instruction set: " << insn_set;
+  }
+}
+
+
+} // namespace llvm
+} // namespace art
diff --git a/compiler/llvm/llvm_compilation_unit.h b/compiler/llvm/llvm_compilation_unit.h
new file mode 100644
index 0000000..a4f0adb
--- /dev/null
+++ b/compiler/llvm/llvm_compilation_unit.h
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_SRC_COMPILER_LLVM_LLVM_COMPILATION_UNIT_H_
+#define ART_SRC_COMPILER_LLVM_LLVM_COMPILATION_UNIT_H_
+
+#include "base/logging.h"
+#include "base/mutex.h"
+#include "dex/compiler_internals.h"
+#include "driver/compiler_driver.h"
+#include "driver/dex_compilation_unit.h"
+#include "globals.h"
+#include "instruction_set.h"
+#include "runtime_support_builder.h"
+#include "runtime_support_llvm_func.h"
+#include "safe_map.h"
+
+#include <UniquePtr.h>
+#include <string>
+#include <vector>
+
+namespace art {
+  class CompiledMethod;
+}
+
+namespace llvm {
+  class Function;
+  class LLVMContext;
+  class Module;
+  class raw_ostream;
+}
+
+namespace art {
+namespace llvm {
+
+class CompilerLLVM;
+class IRBuilder;
+
+class LlvmCompilationUnit {
+ public:
+  ~LlvmCompilationUnit();
+
+  uint32_t GetCompilationUnitId() const {
+    return cunit_id_;
+  }
+
+  InstructionSet GetInstructionSet() const;
+
+  ::llvm::LLVMContext* GetLLVMContext() const {
+    return context_.get();
+  }
+
+  ::llvm::Module* GetModule() const {
+    return module_;
+  }
+
+  IRBuilder* GetIRBuilder() const {
+    return irb_.get();
+  }
+
+  void SetBitcodeFileName(const std::string& bitcode_filename) {
+    bitcode_filename_ = bitcode_filename;
+  }
+
+  LLVMInfo* GetQuickContext() const {
+    return llvm_info_.get();
+  }
+  void SetCompilerDriver(CompilerDriver* driver) {
+    driver_ = driver;
+  }
+  DexCompilationUnit* GetDexCompilationUnit() {
+    return dex_compilation_unit_;
+  }
+  void SetDexCompilationUnit(DexCompilationUnit* dex_compilation_unit) {
+    dex_compilation_unit_ = dex_compilation_unit;
+  }
+
+  bool Materialize();
+
+  bool IsMaterialized() const {
+    return !elf_object_.empty();
+  }
+
+  const std::string& GetElfObject() const {
+    DCHECK(IsMaterialized());
+    return elf_object_;
+  }
+
+ private:
+  LlvmCompilationUnit(const CompilerLLVM* compiler_llvm,
+                      uint32_t cunit_id);
+
+  const CompilerLLVM* compiler_llvm_;
+  const uint32_t cunit_id_;
+
+  UniquePtr< ::llvm::LLVMContext> context_;
+  UniquePtr<IRBuilder> irb_;
+  UniquePtr<RuntimeSupportBuilder> runtime_support_;
+  ::llvm::Module* module_; // Managed by context_
+  UniquePtr<IntrinsicHelper> intrinsic_helper_;
+  UniquePtr<LLVMInfo> llvm_info_;
+  CompilerDriver* driver_;
+  DexCompilationUnit* dex_compilation_unit_;
+
+  std::string bitcode_filename_;
+
+  std::string elf_object_;
+
+  SafeMap<const ::llvm::Function*, CompiledMethod*> compiled_methods_map_;
+
+  void CheckCodeAlign(uint32_t offset) const;
+
+  void DumpBitcodeToFile();
+  void DumpBitcodeToString(std::string& str_buffer);
+
+  bool MaterializeToString(std::string& str_buffer);
+  bool MaterializeToRawOStream(::llvm::raw_ostream& out_stream);
+
+  friend class CompilerLLVM;  // For LlvmCompilationUnit constructor
+};
+
+} // namespace llvm
+} // namespace art
+
+#endif // ART_SRC_COMPILER_LLVM_LLVM_COMPILATION_UNIT_H_
diff --git a/compiler/llvm/md_builder.cc b/compiler/llvm/md_builder.cc
new file mode 100644
index 0000000..3884f51
--- /dev/null
+++ b/compiler/llvm/md_builder.cc
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+
+#include "md_builder.h"
+
+#include "llvm/IR/MDBuilder.h"
+
+#include <string>
+
+namespace art {
+namespace llvm {
+
+
+::llvm::MDNode* MDBuilder::GetTBAASpecialType(TBAASpecialType sty_id) {
+  DCHECK_GE(sty_id, 0) << "Unknown TBAA special type: " << sty_id;
+  DCHECK_LT(sty_id, MAX_TBAA_SPECIAL_TYPE) << "Unknown TBAA special type: " << sty_id;
+  DCHECK(tbaa_root_ != NULL);
+
+  ::llvm::MDNode*& spec_ty = tbaa_special_type_[sty_id];
+  if (spec_ty == NULL) {
+    switch (sty_id) {
+    case kTBAARegister:     spec_ty = createTBAANode("Register", tbaa_root_); break;
+    case kTBAAStackTemp:    spec_ty = createTBAANode("StackTemp", tbaa_root_); break;
+    case kTBAAHeapArray:    spec_ty = createTBAANode("HeapArray", tbaa_root_); break;
+    case kTBAAHeapInstance: spec_ty = createTBAANode("HeapInstance", tbaa_root_); break;
+    case kTBAAHeapStatic:   spec_ty = createTBAANode("HeapStatic", tbaa_root_); break;
+    case kTBAAJRuntime:     spec_ty = createTBAANode("JRuntime", tbaa_root_); break;
+    case kTBAARuntimeInfo:  spec_ty = createTBAANode("RuntimeInfo",
+                                                     GetTBAASpecialType(kTBAAJRuntime)); break;
+    case kTBAAShadowFrame:  spec_ty = createTBAANode("ShadowFrame",
+                                                     GetTBAASpecialType(kTBAAJRuntime)); break;
+    case kTBAAConstJObject: spec_ty = createTBAANode("ConstJObject", tbaa_root_, true); break;
+    default:
+      LOG(FATAL) << "Unknown TBAA special type: " << sty_id;
+      break;
+    }
+  }
+  return spec_ty;
+}
+
+::llvm::MDNode* MDBuilder::GetTBAAMemoryJType(TBAASpecialType sty_id, JType jty_id) {
+  DCHECK(sty_id == kTBAAHeapArray ||
+         sty_id == kTBAAHeapInstance ||
+         sty_id == kTBAAHeapStatic) << "SpecialType must be array, instance, or static";
+
+  DCHECK_GE(jty_id, 0) << "Unknown JType: " << jty_id;
+  DCHECK_LT(jty_id, MAX_JTYPE) << "Unknown JType: " << jty_id;
+  DCHECK_NE(jty_id, kVoid) << "Can't load/store Void type!";
+
+  std::string name;
+  size_t sty_mapped_index = 0;
+  switch (sty_id) {
+  case kTBAAHeapArray:    sty_mapped_index = 0; name = "HeapArray "; break;
+  case kTBAAHeapInstance: sty_mapped_index = 1; name = "HeapInstance "; break;
+  case kTBAAHeapStatic:   sty_mapped_index = 2; name = "HeapStatic "; break;
+  default:
+    LOG(FATAL) << "Unknown TBAA special type: " << sty_id;
+    break;
+  }
+
+  ::llvm::MDNode*& spec_ty = tbaa_memory_jtype_[sty_mapped_index][jty_id];
+  if (spec_ty != NULL) {
+    return spec_ty;
+  }
+
+  switch (jty_id) {
+  case kBoolean: name += "Boolean"; break;
+  case kByte:    name += "Byte"; break;
+  case kChar:    name += "Char"; break;
+  case kShort:   name += "Short"; break;
+  case kInt:     name += "Int"; break;
+  case kLong:    name += "Long"; break;
+  case kFloat:   name += "Float"; break;
+  case kDouble:  name += "Double"; break;
+  case kObject:  name += "Object"; break;
+  default:
+    LOG(FATAL) << "Unknown JType: " << jty_id;
+    break;
+  }
+
+  spec_ty = createTBAANode(name, GetTBAASpecialType(sty_id));
+  return spec_ty;
+}
+
+
+} // namespace llvm
+} // namespace art
diff --git a/compiler/llvm/md_builder.h b/compiler/llvm/md_builder.h
new file mode 100644
index 0000000..79a7caa
--- /dev/null
+++ b/compiler/llvm/md_builder.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_SRC_COMPILER_LLVM_MD_BUILDER_H_
+#define ART_SRC_COMPILER_LLVM_MD_BUILDER_H_
+
+#include "backend_types.h"
+
+#include "llvm/IR/MDBuilder.h"
+
+#include <cstring>
+
+namespace llvm {
+  class LLVMContext;
+  class MDNode;
+}
+
+namespace art {
+namespace llvm {
+
+typedef ::llvm::MDBuilder LLVMMDBuilder;
+
+class MDBuilder : public LLVMMDBuilder {
+ public:
+  MDBuilder(::llvm::LLVMContext& context)
+     : LLVMMDBuilder(context), tbaa_root_(createTBAARoot("Art TBAA Root")) {
+    std::memset(tbaa_special_type_, 0, sizeof(tbaa_special_type_));
+    std::memset(tbaa_memory_jtype_, 0, sizeof(tbaa_memory_jtype_));
+
+    // Pre-generate the MDNode for static branch prediction
+    // 64 and 4 are the llvm.expect's default values
+    expect_cond_[kLikely] = createBranchWeights(64, 4);
+    expect_cond_[kUnlikely] = createBranchWeights(4, 64);
+  }
+
+  ::llvm::MDNode* GetTBAASpecialType(TBAASpecialType special_ty);
+  ::llvm::MDNode* GetTBAAMemoryJType(TBAASpecialType special_ty, JType j_ty);
+
+  ::llvm::MDNode* GetBranchWeights(ExpectCond expect) {
+    DCHECK_LT(expect, MAX_EXPECT) << "MAX_EXPECT is not for branch weight";
+    return expect_cond_[expect];
+  }
+
+ private:
+  ::llvm::MDNode* const tbaa_root_;
+  ::llvm::MDNode* tbaa_special_type_[MAX_TBAA_SPECIAL_TYPE];
+  // There are 3 categories of memory types will not alias: array element, instance field, and
+  // static field.
+  ::llvm::MDNode* tbaa_memory_jtype_[3][MAX_JTYPE];
+
+  ::llvm::MDNode* expect_cond_[MAX_EXPECT];
+};
+
+
+} // namespace llvm
+} // namespace art
+
+#endif // ART_SRC_COMPILER_LLVM_MD_BUILDER_H_
diff --git a/compiler/llvm/runtime_support_builder.cc b/compiler/llvm/runtime_support_builder.cc
new file mode 100644
index 0000000..28405f6
--- /dev/null
+++ b/compiler/llvm/runtime_support_builder.cc
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2011 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 "runtime_support_builder.h"
+
+#include "gc/accounting/card_table.h"
+#include "ir_builder.h"
+#include "monitor.h"
+#include "mirror/object.h"
+#include "thread.h"
+
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+
+using namespace llvm;
+
+namespace art {
+namespace llvm {
+
+using namespace runtime_support;
+
+
+RuntimeSupportBuilder::RuntimeSupportBuilder(::llvm::LLVMContext& context,
+                                             ::llvm::Module& module,
+                                             IRBuilder& irb)
+    : context_(context), module_(module), irb_(irb)
+{
+  memset(target_runtime_support_func_, 0, sizeof(target_runtime_support_func_));
+#define GET_RUNTIME_SUPPORT_FUNC_DECL(ID, NAME) \
+  do { \
+    ::llvm::Function* fn = module_.getFunction(#NAME); \
+    DCHECK_NE(fn, (void*)NULL) << "Function not found: " << #NAME; \
+    runtime_support_func_decls_[runtime_support::ID] = fn; \
+  } while (0);
+
+#include "runtime_support_llvm_func_list.h"
+  RUNTIME_SUPPORT_FUNC_LIST(GET_RUNTIME_SUPPORT_FUNC_DECL)
+#undef RUNTIME_SUPPORT_FUNC_LIST
+#undef GET_RUNTIME_SUPPORT_FUNC_DECL
+}
+
+
+/* Thread */
+
+::llvm::Value* RuntimeSupportBuilder::EmitGetCurrentThread() {
+  Function* func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread);
+  CallInst* call_inst = irb_.CreateCall(func);
+  call_inst->setOnlyReadsMemory();
+  irb_.SetTBAA(call_inst, kTBAAConstJObject);
+  return call_inst;
+}
+
+::llvm::Value* RuntimeSupportBuilder::EmitLoadFromThreadOffset(int64_t offset, ::llvm::Type* type,
+                                                             TBAASpecialType s_ty) {
+  Value* thread = EmitGetCurrentThread();
+  return irb_.LoadFromObjectOffset(thread, offset, type, s_ty);
+}
+
+void RuntimeSupportBuilder::EmitStoreToThreadOffset(int64_t offset, ::llvm::Value* value,
+                                                    TBAASpecialType s_ty) {
+  Value* thread = EmitGetCurrentThread();
+  irb_.StoreToObjectOffset(thread, offset, value, s_ty);
+}
+
+::llvm::Value* RuntimeSupportBuilder::EmitSetCurrentThread(::llvm::Value* thread) {
+  Function* func = GetRuntimeSupportFunction(runtime_support::SetCurrentThread);
+  return irb_.CreateCall(func, thread);
+}
+
+
+/* ShadowFrame */
+
+::llvm::Value* RuntimeSupportBuilder::EmitPushShadowFrame(::llvm::Value* new_shadow_frame,
+                                                        ::llvm::Value* method,
+                                                        uint32_t num_vregs) {
+  Value* old_shadow_frame = EmitLoadFromThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
+                                                     irb_.getArtFrameTy()->getPointerTo(),
+                                                     kTBAARuntimeInfo);
+  EmitStoreToThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
+                          new_shadow_frame,
+                          kTBAARuntimeInfo);
+
+  // Store the method pointer
+  irb_.StoreToObjectOffset(new_shadow_frame,
+                           ShadowFrame::MethodOffset(),
+                           method,
+                           kTBAAShadowFrame);
+
+  // Store the number of vregs
+  irb_.StoreToObjectOffset(new_shadow_frame,
+                           ShadowFrame::NumberOfVRegsOffset(),
+                           irb_.getInt32(num_vregs),
+                           kTBAAShadowFrame);
+
+  // Store the link to previous shadow frame
+  irb_.StoreToObjectOffset(new_shadow_frame,
+                           ShadowFrame::LinkOffset(),
+                           old_shadow_frame,
+                           kTBAAShadowFrame);
+
+  return old_shadow_frame;
+}
+
+::llvm::Value*
+RuntimeSupportBuilder::EmitPushShadowFrameNoInline(::llvm::Value* new_shadow_frame,
+                                                   ::llvm::Value* method,
+                                                   uint32_t num_vregs) {
+  Function* func = GetRuntimeSupportFunction(runtime_support::PushShadowFrame);
+  ::llvm::CallInst* call_inst =
+      irb_.CreateCall4(func,
+                       EmitGetCurrentThread(),
+                       new_shadow_frame,
+                       method,
+                       irb_.getInt32(num_vregs));
+  irb_.SetTBAA(call_inst, kTBAARuntimeInfo);
+  return call_inst;
+}
+
+void RuntimeSupportBuilder::EmitPopShadowFrame(::llvm::Value* old_shadow_frame) {
+  // Store old shadow frame to TopShadowFrame
+  EmitStoreToThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
+                          old_shadow_frame,
+                          kTBAARuntimeInfo);
+}
+
+
+/* Exception */
+
+::llvm::Value* RuntimeSupportBuilder::EmitGetAndClearException() {
+  Function* slow_func = GetRuntimeSupportFunction(runtime_support::GetAndClearException);
+  return irb_.CreateCall(slow_func, EmitGetCurrentThread());
+}
+
+::llvm::Value* RuntimeSupportBuilder::EmitIsExceptionPending() {
+  Value* exception = EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
+                                              irb_.getJObjectTy(),
+                                              kTBAARuntimeInfo);
+  // If exception not null
+  return irb_.CreateIsNotNull(exception);
+}
+
+
+/* Suspend */
+
+void RuntimeSupportBuilder::EmitTestSuspend() {
+  Function* slow_func = GetRuntimeSupportFunction(runtime_support::TestSuspend);
+  CallInst* call_inst = irb_.CreateCall(slow_func, EmitGetCurrentThread());
+  irb_.SetTBAA(call_inst, kTBAAJRuntime);
+}
+
+
+/* Monitor */
+
+void RuntimeSupportBuilder::EmitLockObject(::llvm::Value* object) {
+  Value* monitor =
+      irb_.LoadFromObjectOffset(object,
+                                mirror::Object::MonitorOffset().Int32Value(),
+                                irb_.getJIntTy(),
+                                kTBAARuntimeInfo);
+
+  Value* real_monitor =
+      irb_.CreateAnd(monitor, ~(LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
+
+  // Is thin lock, unheld and not recursively acquired.
+  Value* unheld = irb_.CreateICmpEQ(real_monitor, irb_.getInt32(0));
+
+  Function* parent_func = irb_.GetInsertBlock()->getParent();
+  BasicBlock* bb_fast = BasicBlock::Create(context_, "lock_fast", parent_func);
+  BasicBlock* bb_slow = BasicBlock::Create(context_, "lock_slow", parent_func);
+  BasicBlock* bb_cont = BasicBlock::Create(context_, "lock_cont", parent_func);
+  irb_.CreateCondBr(unheld, bb_fast, bb_slow, kLikely);
+
+  irb_.SetInsertPoint(bb_fast);
+
+  // Calculate new monitor: new = old | (lock_id << LW_LOCK_OWNER_SHIFT)
+  Value* lock_id =
+      EmitLoadFromThreadOffset(Thread::ThinLockIdOffset().Int32Value(),
+                               irb_.getInt32Ty(), kTBAARuntimeInfo);
+
+  Value* owner = irb_.CreateShl(lock_id, LW_LOCK_OWNER_SHIFT);
+  Value* new_monitor = irb_.CreateOr(monitor, owner);
+
+  // Atomically update monitor.
+  Value* old_monitor =
+      irb_.CompareExchangeObjectOffset(object,
+                                       mirror::Object::MonitorOffset().Int32Value(),
+                                       monitor, new_monitor, kTBAARuntimeInfo);
+
+  Value* retry_slow_path = irb_.CreateICmpEQ(old_monitor, monitor);
+  irb_.CreateCondBr(retry_slow_path, bb_cont, bb_slow, kLikely);
+
+  irb_.SetInsertPoint(bb_slow);
+  Function* slow_func = GetRuntimeSupportFunction(runtime_support::LockObject);
+  irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
+  irb_.CreateBr(bb_cont);
+
+  irb_.SetInsertPoint(bb_cont);
+}
+
+void RuntimeSupportBuilder::EmitUnlockObject(::llvm::Value* object) {
+  Value* lock_id =
+      EmitLoadFromThreadOffset(Thread::ThinLockIdOffset().Int32Value(),
+                               irb_.getJIntTy(),
+                               kTBAARuntimeInfo);
+  Value* monitor =
+      irb_.LoadFromObjectOffset(object,
+                                mirror::Object::MonitorOffset().Int32Value(),
+                                irb_.getJIntTy(),
+                                kTBAARuntimeInfo);
+
+  Value* my_monitor = irb_.CreateShl(lock_id, LW_LOCK_OWNER_SHIFT);
+  Value* hash_state = irb_.CreateAnd(monitor, (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
+  Value* real_monitor = irb_.CreateAnd(monitor, ~(LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
+
+  // Is thin lock, held by us and not recursively acquired
+  Value* is_fast_path = irb_.CreateICmpEQ(real_monitor, my_monitor);
+
+  Function* parent_func = irb_.GetInsertBlock()->getParent();
+  BasicBlock* bb_fast = BasicBlock::Create(context_, "unlock_fast", parent_func);
+  BasicBlock* bb_slow = BasicBlock::Create(context_, "unlock_slow", parent_func);
+  BasicBlock* bb_cont = BasicBlock::Create(context_, "unlock_cont", parent_func);
+  irb_.CreateCondBr(is_fast_path, bb_fast, bb_slow, kLikely);
+
+  irb_.SetInsertPoint(bb_fast);
+  // Set all bits to zero (except hash state)
+  irb_.StoreToObjectOffset(object,
+                           mirror::Object::MonitorOffset().Int32Value(),
+                           hash_state,
+                           kTBAARuntimeInfo);
+  irb_.CreateBr(bb_cont);
+
+  irb_.SetInsertPoint(bb_slow);
+  Function* slow_func = GetRuntimeSupportFunction(runtime_support::UnlockObject);
+  irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
+  irb_.CreateBr(bb_cont);
+
+  irb_.SetInsertPoint(bb_cont);
+}
+
+
+void RuntimeSupportBuilder::EmitMarkGCCard(::llvm::Value* value, ::llvm::Value* target_addr) {
+  Function* parent_func = irb_.GetInsertBlock()->getParent();
+  BasicBlock* bb_mark_gc_card = BasicBlock::Create(context_, "mark_gc_card", parent_func);
+  BasicBlock* bb_cont = BasicBlock::Create(context_, "mark_gc_card_cont", parent_func);
+
+  ::llvm::Value* not_null = irb_.CreateIsNotNull(value);
+  irb_.CreateCondBr(not_null, bb_mark_gc_card, bb_cont);
+
+  irb_.SetInsertPoint(bb_mark_gc_card);
+  Value* card_table = EmitLoadFromThreadOffset(Thread::CardTableOffset().Int32Value(),
+                                               irb_.getInt8Ty()->getPointerTo(),
+                                               kTBAAConstJObject);
+  Value* target_addr_int = irb_.CreatePtrToInt(target_addr, irb_.getPtrEquivIntTy());
+  Value* card_no = irb_.CreateLShr(target_addr_int,
+                                   irb_.getPtrEquivInt(gc::accounting::CardTable::kCardShift));
+  Value* card_table_entry = irb_.CreateGEP(card_table, card_no);
+  irb_.CreateStore(irb_.getInt8(gc::accounting::CardTable::kCardDirty), card_table_entry,
+                   kTBAARuntimeInfo);
+  irb_.CreateBr(bb_cont);
+
+  irb_.SetInsertPoint(bb_cont);
+}
+
+
+} // namespace llvm
+} // namespace art
diff --git a/compiler/llvm/runtime_support_builder.h b/compiler/llvm/runtime_support_builder.h
new file mode 100644
index 0000000..267b406
--- /dev/null
+++ b/compiler/llvm/runtime_support_builder.h
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_BUILDER_H_
+#define ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_BUILDER_H_
+
+#include "backend_types.h"
+#include "base/logging.h"
+#include "runtime_support_llvm_func.h"
+
+#include <stdint.h>
+
+namespace llvm {
+  class LLVMContext;
+  class Module;
+  class Function;
+  class Type;
+  class Value;
+}
+
+namespace art {
+namespace llvm {
+
+class IRBuilder;
+
+
+class RuntimeSupportBuilder {
+ public:
+  RuntimeSupportBuilder(::llvm::LLVMContext& context, ::llvm::Module& module, IRBuilder& irb);
+
+  /* Thread */
+  virtual ::llvm::Value* EmitGetCurrentThread();
+  virtual ::llvm::Value* EmitLoadFromThreadOffset(int64_t offset, ::llvm::Type* type,
+                                                TBAASpecialType s_ty);
+  virtual void EmitStoreToThreadOffset(int64_t offset, ::llvm::Value* value,
+                                       TBAASpecialType s_ty);
+  virtual ::llvm::Value* EmitSetCurrentThread(::llvm::Value* thread);
+
+  /* ShadowFrame */
+  virtual ::llvm::Value* EmitPushShadowFrame(::llvm::Value* new_shadow_frame,
+                                           ::llvm::Value* method, uint32_t num_vregs);
+  virtual ::llvm::Value* EmitPushShadowFrameNoInline(::llvm::Value* new_shadow_frame,
+                                                   ::llvm::Value* method, uint32_t num_vregs);
+  virtual void EmitPopShadowFrame(::llvm::Value* old_shadow_frame);
+
+  /* Exception */
+  virtual ::llvm::Value* EmitGetAndClearException();
+  virtual ::llvm::Value* EmitIsExceptionPending();
+
+  /* Suspend */
+  virtual void EmitTestSuspend();
+
+  /* Monitor */
+  virtual void EmitLockObject(::llvm::Value* object);
+  virtual void EmitUnlockObject(::llvm::Value* object);
+
+  /* MarkGCCard */
+  virtual void EmitMarkGCCard(::llvm::Value* value, ::llvm::Value* target_addr);
+
+  ::llvm::Function* GetRuntimeSupportFunction(runtime_support::RuntimeId id) {
+    if (id >= 0 && id < runtime_support::MAX_ID) {
+      return runtime_support_func_decls_[id];
+    } else {
+      LOG(ERROR) << "Unknown runtime function id: " << id;
+      return NULL;
+    }
+  }
+
+  virtual ~RuntimeSupportBuilder() {}
+
+ protected:
+  ::llvm::LLVMContext& context_;
+  ::llvm::Module& module_;
+  IRBuilder& irb_;
+
+ private:
+  ::llvm::Function* runtime_support_func_decls_[runtime_support::MAX_ID];
+  bool target_runtime_support_func_[runtime_support::MAX_ID];
+};
+
+
+} // namespace llvm
+} // namespace art
+
+#endif // ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_BUILDER_H_
diff --git a/compiler/llvm/runtime_support_builder_arm.cc b/compiler/llvm/runtime_support_builder_arm.cc
new file mode 100644
index 0000000..57a9971
--- /dev/null
+++ b/compiler/llvm/runtime_support_builder_arm.cc
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+#include "runtime_support_builder_arm.h"
+
+#include "ir_builder.h"
+#include "thread.h"
+#include "utils_llvm.h"
+
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/InlineAsm.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+
+#include <vector>
+
+using namespace llvm;
+
+namespace {
+
+char LDRSTRSuffixByType(art::llvm::IRBuilder& irb, ::llvm::Type* type) {
+  int width = type->isPointerTy() ?
+              irb.getSizeOfPtrEquivInt()*8 :
+              ::llvm::cast<IntegerType>(type)->getBitWidth();
+  switch (width) {
+    case 8:  return 'b';
+    case 16: return 'h';
+    case 32: return ' ';
+    default:
+      LOG(FATAL) << "Unsupported width: " << width;
+      return ' ';
+  }
+}
+
+} // namespace
+
+namespace art {
+namespace llvm {
+
+/* Thread */
+
+::llvm::Value* RuntimeSupportBuilderARM::EmitGetCurrentThread() {
+  Function* ori_func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread);
+  InlineAsm* func = InlineAsm::get(ori_func->getFunctionType(), "mov $0, r9", "=r", false);
+  CallInst* thread = irb_.CreateCall(func);
+  thread->setDoesNotAccessMemory();
+  irb_.SetTBAA(thread, kTBAAConstJObject);
+  return thread;
+}
+
+::llvm::Value* RuntimeSupportBuilderARM::EmitLoadFromThreadOffset(int64_t offset, ::llvm::Type* type,
+                                                                TBAASpecialType s_ty) {
+  FunctionType* func_ty = FunctionType::get(/*Result=*/type,
+                                            /*isVarArg=*/false);
+  std::string inline_asm(StringPrintf("ldr%c $0, [r9, #%d]",
+                                      LDRSTRSuffixByType(irb_, type),
+                                      static_cast<int>(offset)));
+  InlineAsm* func = InlineAsm::get(func_ty, inline_asm, "=r", true);
+  CallInst* result = irb_.CreateCall(func);
+  result->setOnlyReadsMemory();
+  irb_.SetTBAA(result, s_ty);
+  return result;
+}
+
+void RuntimeSupportBuilderARM::EmitStoreToThreadOffset(int64_t offset, ::llvm::Value* value,
+                                                       TBAASpecialType s_ty) {
+  FunctionType* func_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_),
+                                            /*Params=*/value->getType(),
+                                            /*isVarArg=*/false);
+  std::string inline_asm(StringPrintf("str%c $0, [r9, #%d]",
+                                      LDRSTRSuffixByType(irb_, value->getType()),
+                                      static_cast<int>(offset)));
+  InlineAsm* func = InlineAsm::get(func_ty, inline_asm, "r", true);
+  CallInst* call_inst = irb_.CreateCall(func, value);
+  irb_.SetTBAA(call_inst, s_ty);
+}
+
+::llvm::Value*
+RuntimeSupportBuilderARM::EmitSetCurrentThread(::llvm::Value* thread) {
+  // Separate to two InlineAsm: The first one produces the return value, while the second,
+  // sets the current thread.
+  // LLVM can delete the first one if the caller in LLVM IR doesn't use the return value.
+  //
+  // Here we don't call EmitGetCurrentThread, because we mark it as DoesNotAccessMemory and
+  // ConstJObject. We denote side effect to "true" below instead, so LLVM won't
+  // reorder these instructions incorrectly.
+  Function* ori_func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread);
+  InlineAsm* func = InlineAsm::get(ori_func->getFunctionType(), "mov $0, r9", "=r", true);
+  CallInst* old_thread_register = irb_.CreateCall(func);
+  old_thread_register->setOnlyReadsMemory();
+
+  FunctionType* func_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_),
+                                            /*Params=*/irb_.getJObjectTy(),
+                                            /*isVarArg=*/false);
+  func = InlineAsm::get(func_ty, "mov r9, $0", "r", true);
+  irb_.CreateCall(func, thread);
+  return old_thread_register;
+}
+
+
+/* Monitor */
+
+void RuntimeSupportBuilderARM::EmitLockObject(::llvm::Value* object) {
+  RuntimeSupportBuilder::EmitLockObject(object);
+  FunctionType* func_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_),
+                                            /*isVarArg=*/false);
+  InlineAsm* func = InlineAsm::get(func_ty, "dmb sy", "", true);
+  irb_.CreateCall(func);
+}
+
+void RuntimeSupportBuilderARM::EmitUnlockObject(::llvm::Value* object) {
+  RuntimeSupportBuilder::EmitUnlockObject(object);
+  FunctionType* func_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_),
+                                            /*isVarArg=*/false);
+  InlineAsm* func = InlineAsm::get(func_ty, "dmb sy", "", true);
+  irb_.CreateCall(func);
+}
+
+} // namespace llvm
+} // namespace art
diff --git a/compiler/llvm/runtime_support_builder_arm.h b/compiler/llvm/runtime_support_builder_arm.h
new file mode 100644
index 0000000..3c5972f
--- /dev/null
+++ b/compiler/llvm/runtime_support_builder_arm.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_BUILDER_ARM_H_
+#define ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_BUILDER_ARM_H_
+
+#include "runtime_support_builder.h"
+
+namespace art {
+namespace llvm {
+
+class RuntimeSupportBuilderARM : public RuntimeSupportBuilder {
+ public:
+  RuntimeSupportBuilderARM(::llvm::LLVMContext& context, ::llvm::Module& module, IRBuilder& irb)
+    : RuntimeSupportBuilder(context, module, irb) {}
+
+  /* Thread */
+  virtual ::llvm::Value* EmitGetCurrentThread();
+  virtual ::llvm::Value* EmitLoadFromThreadOffset(int64_t offset, ::llvm::Type* type,
+                                                TBAASpecialType s_ty);
+  virtual void EmitStoreToThreadOffset(int64_t offset, ::llvm::Value* value,
+                                       TBAASpecialType s_ty);
+  virtual ::llvm::Value* EmitSetCurrentThread(::llvm::Value* thread);
+
+  /* Monitor */
+  virtual void EmitLockObject(::llvm::Value* object);
+  virtual void EmitUnlockObject(::llvm::Value* object);
+};
+
+} // namespace llvm
+} // namespace art
+
+#endif // ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_BUILDER_ARM_H_
diff --git a/compiler/llvm/runtime_support_builder_thumb2.cc b/compiler/llvm/runtime_support_builder_thumb2.cc
new file mode 100644
index 0000000..2b9170c
--- /dev/null
+++ b/compiler/llvm/runtime_support_builder_thumb2.cc
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#include "runtime_support_builder_thumb2.h"
+
+#include "ir_builder.h"
+#include "mirror/object.h"
+#include "monitor.h"
+#include "thread.h"
+#include "utils_llvm.h"
+
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/InlineAsm.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+
+#include <inttypes.h>
+#include <vector>
+
+using namespace llvm;
+
+namespace art {
+namespace llvm {
+
+
+void RuntimeSupportBuilderThumb2::EmitLockObject(::llvm::Value* object) {
+  FunctionType* func_ty = FunctionType::get(/*Result=*/irb_.getInt32Ty(),
+                                            /*Params=*/irb_.getJObjectTy(),
+                                            /*isVarArg=*/false);
+  // $0: result
+  // $1: object
+  // $2: temp
+  // $3: temp
+  std::string asms;
+  StringAppendF(&asms, "add $3, $1, #%"PRId32"\n", mirror::Object::MonitorOffset().Int32Value());
+  StringAppendF(&asms, "ldr $2, [r9, #%"PRId32"]\n", Thread::ThinLockIdOffset().Int32Value());
+  StringAppendF(&asms, "ldrex $0, [$3]\n");
+  StringAppendF(&asms, "lsl $2, $2, %d\n", LW_LOCK_OWNER_SHIFT);
+  StringAppendF(&asms, "bfi $2, $0, #0, #%d\n", LW_LOCK_OWNER_SHIFT - 1);
+  StringAppendF(&asms, "bfc $0, #%d, #%d\n", LW_HASH_STATE_SHIFT, LW_LOCK_OWNER_SHIFT - 1);
+  StringAppendF(&asms, "cmp $0, #0\n");
+  StringAppendF(&asms, "it eq\n");
+  StringAppendF(&asms, "strexeq $0, $2, [$3]\n");
+
+  InlineAsm* func = InlineAsm::get(func_ty, asms, "=&l,l,~l,~l", true);
+
+  ::llvm::Value* retry_slow_path = irb_.CreateCall(func, object);
+  retry_slow_path = irb_.CreateICmpNE(retry_slow_path, irb_.getJInt(0));
+
+  ::llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
+  BasicBlock* basic_block_lock = BasicBlock::Create(context_, "lock", parent_func);
+  BasicBlock* basic_block_cont = BasicBlock::Create(context_, "lock_cont", parent_func);
+  irb_.CreateCondBr(retry_slow_path, basic_block_lock, basic_block_cont, kUnlikely);
+
+  irb_.SetInsertPoint(basic_block_lock);
+  Function* slow_func = GetRuntimeSupportFunction(runtime_support::LockObject);
+  irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
+  irb_.CreateBr(basic_block_cont);
+
+  irb_.SetInsertPoint(basic_block_cont);
+  { // Memory barrier
+    FunctionType* asm_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_),
+                                              /*isVarArg=*/false);
+    InlineAsm* func = InlineAsm::get(asm_ty, "dmb sy", "", true);
+    irb_.CreateCall(func);
+  }
+}
+
+
+} // namespace llvm
+} // namespace art
diff --git a/compiler/llvm/runtime_support_builder_thumb2.h b/compiler/llvm/runtime_support_builder_thumb2.h
new file mode 100644
index 0000000..4762a26
--- /dev/null
+++ b/compiler/llvm/runtime_support_builder_thumb2.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_BUILDER_THUMB2_H_
+#define ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_BUILDER_THUMB2_H_
+
+#include "runtime_support_builder_arm.h"
+
+namespace art {
+namespace llvm {
+
+class RuntimeSupportBuilderThumb2 : public RuntimeSupportBuilderARM {
+ public:
+  RuntimeSupportBuilderThumb2(::llvm::LLVMContext& context, ::llvm::Module& module, IRBuilder& irb)
+    : RuntimeSupportBuilderARM(context, module, irb) {}
+
+  /* Monitor */
+  virtual void EmitLockObject(::llvm::Value* object);
+};
+
+} // namespace llvm
+} // namespace art
+
+#endif // ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_BUILDER_THUMB2_H_
diff --git a/compiler/llvm/runtime_support_builder_x86.cc b/compiler/llvm/runtime_support_builder_x86.cc
new file mode 100644
index 0000000..eed0b63
--- /dev/null
+++ b/compiler/llvm/runtime_support_builder_x86.cc
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#include "runtime_support_builder_x86.h"
+
+#include "base/stringprintf.h"
+#include "ir_builder.h"
+#include "thread.h"
+#include "utils_llvm.h"
+
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/InlineAsm.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+
+#include <vector>
+
+using namespace llvm;
+
+namespace art {
+namespace llvm {
+
+
+::llvm::Value* RuntimeSupportBuilderX86::EmitGetCurrentThread() {
+  Function* ori_func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread);
+  std::string inline_asm(StringPrintf("mov %%fs:%d, $0", Thread::SelfOffset().Int32Value()));
+  InlineAsm* func = InlineAsm::get(ori_func->getFunctionType(), inline_asm, "=r", false);
+  CallInst* thread = irb_.CreateCall(func);
+  thread->setDoesNotAccessMemory();
+  irb_.SetTBAA(thread, kTBAAConstJObject);
+  return thread;
+}
+
+::llvm::Value* RuntimeSupportBuilderX86::EmitLoadFromThreadOffset(int64_t offset, ::llvm::Type* type,
+                                                                TBAASpecialType s_ty) {
+  FunctionType* func_ty = FunctionType::get(/*Result=*/type,
+                                            /*isVarArg=*/false);
+  std::string inline_asm(StringPrintf("mov %%fs:%d, $0", static_cast<int>(offset)));
+  InlineAsm* func = InlineAsm::get(func_ty, inline_asm, "=r", true);
+  CallInst* result = irb_.CreateCall(func);
+  result->setOnlyReadsMemory();
+  irb_.SetTBAA(result, s_ty);
+  return result;
+}
+
+void RuntimeSupportBuilderX86::EmitStoreToThreadOffset(int64_t offset, ::llvm::Value* value,
+                                                       TBAASpecialType s_ty) {
+  FunctionType* func_ty = FunctionType::get(/*Result=*/Type::getVoidTy(context_),
+                                            /*Params=*/value->getType(),
+                                            /*isVarArg=*/false);
+  std::string inline_asm(StringPrintf("mov $0, %%fs:%d", static_cast<int>(offset)));
+  InlineAsm* func = InlineAsm::get(func_ty, inline_asm, "r", true);
+  CallInst* call_inst = irb_.CreateCall(func, value);
+  irb_.SetTBAA(call_inst, s_ty);
+}
+
+::llvm::Value* RuntimeSupportBuilderX86::EmitSetCurrentThread(::llvm::Value*) {
+  /* Nothing to be done. */
+  return ::llvm::UndefValue::get(irb_.getJObjectTy());
+}
+
+
+} // namespace llvm
+} // namespace art
diff --git a/compiler/llvm/runtime_support_builder_x86.h b/compiler/llvm/runtime_support_builder_x86.h
new file mode 100644
index 0000000..e5fdbc2
--- /dev/null
+++ b/compiler/llvm/runtime_support_builder_x86.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_BUILDER_X86_H_
+#define ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_BUILDER_X86_H_
+
+#include "runtime_support_builder.h"
+
+namespace art {
+namespace llvm {
+
+class RuntimeSupportBuilderX86 : public RuntimeSupportBuilder {
+ public:
+  RuntimeSupportBuilderX86(::llvm::LLVMContext& context, ::llvm::Module& module, IRBuilder& irb)
+    : RuntimeSupportBuilder(context, module, irb) {}
+
+  /* Thread */
+  virtual ::llvm::Value* EmitGetCurrentThread();
+  virtual ::llvm::Value* EmitLoadFromThreadOffset(int64_t offset, ::llvm::Type* type,
+                                                TBAASpecialType s_ty);
+  virtual void EmitStoreToThreadOffset(int64_t offset, ::llvm::Value* value,
+                                       TBAASpecialType s_ty);
+  virtual ::llvm::Value* EmitSetCurrentThread(::llvm::Value* thread);
+};
+
+} // namespace llvm
+} // namespace art
+
+#endif // ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_BUILDER_X86_H_
diff --git a/compiler/llvm/runtime_support_llvm_func.h b/compiler/llvm/runtime_support_llvm_func.h
new file mode 100644
index 0000000..ac6f3b8
--- /dev/null
+++ b/compiler/llvm/runtime_support_llvm_func.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_FUNC_H_
+#define ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_FUNC_H_
+
+namespace art {
+namespace llvm {
+namespace runtime_support {
+
+  enum RuntimeId {
+#define DEFINE_RUNTIME_SUPPORT_FUNC_ID(ID, NAME) ID,
+#include "runtime_support_llvm_func_list.h"
+    RUNTIME_SUPPORT_FUNC_LIST(DEFINE_RUNTIME_SUPPORT_FUNC_ID)
+#undef RUNTIME_SUPPORT_FUNC_LIST
+#undef DEFINE_RUNTIME_SUPPORT_FUNC_ID
+
+    MAX_ID
+  };
+
+} // namespace runtime_support
+} // namespace llvm
+} // namespace art
+
+#endif // ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_FUNC_H_
diff --git a/compiler/llvm/tools/gen_art_module_cc.sh b/compiler/llvm/tools/gen_art_module_cc.sh
new file mode 100755
index 0000000..c5df333
--- /dev/null
+++ b/compiler/llvm/tools/gen_art_module_cc.sh
@@ -0,0 +1,50 @@
+#!/bin/bash -e
+
+# 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.
+
+SCRIPTDIR=`dirname "$0"`
+cd "${SCRIPTDIR}/.."
+
+mkdir -p generated
+
+OUTPUT_FILE=generated/art_module.cc
+
+echo "// Generated with ${0}" > ${OUTPUT_FILE}
+
+echo '
+
+#pragma GCC diagnostic ignored "-Wframe-larger-than="
+// TODO: Remove this pragma after llc can generate makeLLVMModuleContents()
+// with smaller frame size.
+
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Type.h>
+
+#include <vector>
+
+using namespace llvm;
+
+namespace art {
+namespace llvm {
+
+' >> ${OUTPUT_FILE}
+
+llc -march=cpp -cppgen=contents art_module.ll -o - >> ${OUTPUT_FILE}
+
+echo '
+} // namespace llvm
+} // namespace art' >> ${OUTPUT_FILE}
diff --git a/compiler/llvm/utils_llvm.h b/compiler/llvm/utils_llvm.h
new file mode 100644
index 0000000..2e273f4
--- /dev/null
+++ b/compiler/llvm/utils_llvm.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 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 ART_SRC_UTILS_LLVM_H_
+#define ART_SRC_UTILS_LLVM_H_
+
+#include <llvm/Analysis/Verifier.h>
+
+namespace art {
+
+#ifndef NDEBUG
+#define VERIFY_LLVM_FUNCTION(func) ::llvm::verifyFunction(func, ::llvm::AbortProcessAction)
+#else
+#define VERIFY_LLVM_FUNCTION(func)
+#endif
+
+}  // namespace art
+
+#endif  // ART_SRC_UTILS_LLVM_H_