gbc_expander.cc revision 9a14265c911b2e63bec51a814b8b6fd157745b57
121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao/*
221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao * Copyright (C) 2012 The Android Open Source Project
321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao *
421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao * Licensed under the Apache License, Version 2.0 (the "License");
521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao * you may not use this file except in compliance with the License.
621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao * You may obtain a copy of the License at
721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao *
821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao *      http://www.apache.org/licenses/LICENSE-2.0
921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao *
1021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao * Unless required by applicable law or agreed to in writing, software
1121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao * distributed under the License is distributed on an "AS IS" BASIS,
1221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao * See the License for the specific language governing permissions and
1421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao * limitations under the License.
1521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao */
1621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
1721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao#include "ir_builder.h"
1821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao#include "utils_llvm.h"
1921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
205e869b6560f918837cc6be3a50234deb2be46385TDYa#include "compiler.h"
2121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao#include "greenland/intrinsic_helper.h"
225e869b6560f918837cc6be3a50234deb2be46385TDYa#include "oat_compilation_unit.h"
2321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao#include "object.h"
2421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao#include "thread.h"
255e869b6560f918837cc6be3a50234deb2be46385TDYa#include "verifier/method_verifier.h"
2621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
27efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#include "compiler/compiler_ir.h"
28449a49bedfb72f0d5643977a99346935f1b33c55buzbee#include "compiler/codegen/codegen.h"
29920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYausing art::kMIRIgnoreNullCheck;
30920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYausing art::kMIRIgnoreRangeCheck;
31920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa
3221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao#include <llvm/ADT/STLExtras.h>
3321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao#include <llvm/Intrinsics.h>
34d36a2aceeb17b2b1745fc64a8f1dfc77425d43deLogan Chien#include <llvm/Metadata.h>
3521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao#include <llvm/Pass.h>
3621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao#include <llvm/Support/CFG.h>
3721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao#include <llvm/Support/InstIterator.h>
3821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
3921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao#include <vector>
40aa55887fd30484a77e7775dfbcddbee883ce6380TDYa#include <map>
41aa55887fd30484a77e7775dfbcddbee883ce6380TDYa#include <utility>
4221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
43920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYausing namespace art::compiler_llvm;
4421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
4521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaousing art::greenland::IntrinsicHelper;
4621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
47b259652a72293b4bd3c346bb0e40fb8a7f878fa2Shih-wei Liaonamespace art {
4826f10eed520942d3db754c31941e457048475f61buzbeeextern char RemapShorty(char shortyType);
49b259652a72293b4bd3c346bb0e40fb8a7f878fa2Shih-wei Liao};
50b259652a72293b4bd3c346bb0e40fb8a7f878fa2Shih-wei Liao
5121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaonamespace {
5221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
5321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaoclass GBCExpanderPass : public llvm::FunctionPass {
5421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao private:
5521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  const IntrinsicHelper& intrinsic_helper_;
5621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  IRBuilder& irb_;
5721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
5821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::LLVMContext& context_;
5921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  RuntimeSupportBuilder& rtb_;
6021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
6121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao private:
6221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::AllocaInst* shadow_frame_;
6321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* old_shadow_frame_;
6421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
6521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao private:
66920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  art::Compiler* compiler_;
675e869b6560f918837cc6be3a50234deb2be46385TDYa
68920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  const art::DexFile* dex_file_;
69920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  const art::DexFile::CodeItem* code_item_;
705e869b6560f918837cc6be3a50234deb2be46385TDYa
71920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  art::OatCompilationUnit* oat_compilation_unit_;
725e869b6560f918837cc6be3a50234deb2be46385TDYa
735e869b6560f918837cc6be3a50234deb2be46385TDYa  uint32_t method_idx_;
745e869b6560f918837cc6be3a50234deb2be46385TDYa
755e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::Function* func_;
765e869b6560f918837cc6be3a50234deb2be46385TDYa
775e869b6560f918837cc6be3a50234deb2be46385TDYa  std::vector<llvm::BasicBlock*> basic_blocks_;
785e869b6560f918837cc6be3a50234deb2be46385TDYa
795e869b6560f918837cc6be3a50234deb2be46385TDYa  std::vector<llvm::BasicBlock*> basic_block_landing_pads_;
8055e5e6c5702e3f1f68bd83ae741af769740d9a74TDYa  llvm::BasicBlock* current_bb_;
81aa55887fd30484a77e7775dfbcddbee883ce6380TDYa  std::map<llvm::BasicBlock*, std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*> > >
82aa55887fd30484a77e7775dfbcddbee883ce6380TDYa      landing_pad_phi_mapping_;
835e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::BasicBlock* basic_block_unwind_;
845e869b6560f918837cc6be3a50234deb2be46385TDYa
8567645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  bool changed_;
8667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
875e869b6560f918837cc6be3a50234deb2be46385TDYa private:
8821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  //----------------------------------------------------------------------------
8975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  // Constant for GBC expansion
9075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  //----------------------------------------------------------------------------
9175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  enum IntegerShiftKind {
9275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    kIntegerSHL,
9375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    kIntegerSHR,
9475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    kIntegerUSHR,
9575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  };
9675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
9775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien private:
9875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  //----------------------------------------------------------------------------
9921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Helper function for GBC expansion
10021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  //----------------------------------------------------------------------------
10121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
10221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* ExpandToRuntime(runtime_support::RuntimeId rt,
10321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                               llvm::CallInst& inst);
10421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
1055e869b6560f918837cc6be3a50234deb2be46385TDYa  uint64_t LV2UInt(llvm::Value* lv) {
1065e869b6560f918837cc6be3a50234deb2be46385TDYa    return llvm::cast<llvm::ConstantInt>(lv)->getZExtValue();
1075e869b6560f918837cc6be3a50234deb2be46385TDYa  }
1085e869b6560f918837cc6be3a50234deb2be46385TDYa
1095e869b6560f918837cc6be3a50234deb2be46385TDYa  int64_t LV2SInt(llvm::Value* lv) {
1105e869b6560f918837cc6be3a50234deb2be46385TDYa    return llvm::cast<llvm::ConstantInt>(lv)->getSExtValue();
1115e869b6560f918837cc6be3a50234deb2be46385TDYa  }
1125e869b6560f918837cc6be3a50234deb2be46385TDYa
11321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao private:
11421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // TODO: Almost all Emit* are directly copy-n-paste from MethodCompiler.
11521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Refactor these utility functions from MethodCompiler to avoid forking.
11621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
11767645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  void EmitStackOverflowCheck(llvm::Instruction* first_non_alloca);
11867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
11967645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  void RewriteFunction();
12067645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
12167645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  void RewriteBasicBlock(llvm::BasicBlock* original_block);
12267645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
12367645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  void UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
12467645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien                            llvm::BasicBlock* new_basic_block);
12567645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
12621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
12721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  //----------------------------------------------------------------------------
12821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Dex cache code generation helper function
12921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  //----------------------------------------------------------------------------
130920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  llvm::Value* EmitLoadDexCacheAddr(art::MemberOffset dex_cache_offset);
13121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
13221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
13321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
13421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
13521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
13621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
13721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
13821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
13921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
14021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  //----------------------------------------------------------------------------
14121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Code generation helper function
14221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  //----------------------------------------------------------------------------
14321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* EmitLoadMethodObjectAddr();
14421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
14521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* EmitLoadArrayLength(llvm::Value* array);
14621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
14721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
14821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
14921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
15021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                                     llvm::Value* this_addr);
15121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
15221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
15321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                            llvm::Value* index_value,
15421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                            JType elem_jty);
15521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
15621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao private:
15721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  //----------------------------------------------------------------------------
15821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Expand Greenland intrinsics
15921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  //----------------------------------------------------------------------------
16021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  void Expand_TestSuspend(llvm::CallInst& call_inst);
16121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
1629a129457c233b653c7a8f65c963509267252b0a7TDYa  void Expand_MarkGCCard(llvm::CallInst& call_inst);
1639a129457c233b653c7a8f65c963509267252b0a7TDYa
16421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
16521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
16621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
16721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
16821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  void Expand_LockObject(llvm::Value* obj);
16921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
17021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  void Expand_UnlockObject(llvm::Value* obj);
17121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
17221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
17321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                               llvm::Value* index_value,
17421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                               JType elem_jty);
17521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
17621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  void Expand_ArrayPut(llvm::Value* new_value,
17721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                       llvm::Value* array_addr,
17821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                       llvm::Value* index_value,
17921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                       JType elem_jty);
18021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
18121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  void Expand_FilledNewArray(llvm::CallInst& call_inst);
18221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
18321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
18421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                               llvm::Value* is_volatile_value,
18521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                               llvm::Value* object_addr,
18621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                               JType field_jty);
18721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
18821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  void Expand_IPutFast(llvm::Value* field_offset_value,
18921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                       llvm::Value* is_volatile_value,
19021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                       llvm::Value* object_addr,
19121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                       llvm::Value* new_value,
19221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                       JType field_jty);
19321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
19421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
19521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                               llvm::Value* field_offset_value,
19621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                               llvm::Value* is_volatile_value,
19721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                               JType field_jty);
19821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
19921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  void Expand_SPutFast(llvm::Value* static_storage_addr,
20021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                       llvm::Value* field_offset_value,
20121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                       llvm::Value* is_volatile_value,
20221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                       llvm::Value* new_value,
20321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                       JType field_jty);
20421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
20521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
20621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
20721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
20821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
20921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value*
21021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
21121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
21221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value*
21321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
21421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                           llvm::Value* this_addr);
21521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
21621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
21721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
2184ec8ccdaeee1c4af1a70e1ac0dd482e83df72f38TDYa  llvm::Value* Expand_DivRem(llvm::CallInst& call_inst, bool is_div, JType op_jty);
21921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
220ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  void Expand_AllocaShadowFrame(llvm::Value* num_vregs_value);
22121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
2228e950c117975d23f50ed7e32ca5db01a813c25d0TDYa  void Expand_SetVReg(llvm::Value* entry_idx, llvm::Value* obj);
2238e950c117975d23f50ed7e32ca5db01a813c25d0TDYa
22421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  void Expand_PopShadowFrame();
22521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
22621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
22721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
228a1b2185820e6080864d18a35759cc046dc4ee578TDYa  //----------------------------------------------------------------------------
229a1b2185820e6080864d18a35759cc046dc4ee578TDYa  // Quick
230a1b2185820e6080864d18a35759cc046dc4ee578TDYa  //----------------------------------------------------------------------------
231a1b2185820e6080864d18a35759cc046dc4ee578TDYa
232a1b2185820e6080864d18a35759cc046dc4ee578TDYa  llvm::Value* Expand_FPCompare(llvm::Value* src1_value,
233a1b2185820e6080864d18a35759cc046dc4ee578TDYa                                llvm::Value* src2_value,
234a1b2185820e6080864d18a35759cc046dc4ee578TDYa                                bool gt_bias);
235a1b2185820e6080864d18a35759cc046dc4ee578TDYa
236a1b2185820e6080864d18a35759cc046dc4ee578TDYa  llvm::Value* Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value);
237a1b2185820e6080864d18a35759cc046dc4ee578TDYa
238a1b2185820e6080864d18a35759cc046dc4ee578TDYa  llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
239a1b2185820e6080864d18a35759cc046dc4ee578TDYa                                          llvm::Value* cmp_lt);
240a1b2185820e6080864d18a35759cc046dc4ee578TDYa
241f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* EmitLoadConstantClass(uint32_t dex_pc, uint32_t type_idx);
2425a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* EmitLoadStaticStorage(uint32_t dex_pc, uint32_t type_idx);
2435a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
2445e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::Value* Expand_HLIGet(llvm::CallInst& call_inst, JType field_jty);
2455e869b6560f918837cc6be3a50234deb2be46385TDYa  void Expand_HLIPut(llvm::CallInst& call_inst, JType field_jty);
2465e869b6560f918837cc6be3a50234deb2be46385TDYa
2475a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* Expand_HLSget(llvm::CallInst& call_inst, JType field_jty);
2485a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  void Expand_HLSput(llvm::CallInst& call_inst, JType field_jty);
2495a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
2505a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* Expand_HLArrayGet(llvm::CallInst& call_inst, JType field_jty);
2515a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  void Expand_HLArrayPut(llvm::CallInst& call_inst, JType field_jty);
2525a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
253f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* Expand_ConstString(llvm::CallInst& call_inst);
254f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* Expand_ConstClass(llvm::CallInst& call_inst);
255f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
256f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  void Expand_MonitorEnter(llvm::CallInst& call_inst);
257f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  void Expand_MonitorExit(llvm::CallInst& call_inst);
258f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
259f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  void Expand_HLCheckCast(llvm::CallInst& call_inst);
260f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* Expand_InstanceOf(llvm::CallInst& call_inst);
261f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
262f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* Expand_NewInstance(llvm::CallInst& call_inst);
263f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
264f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* Expand_HLInvoke(llvm::CallInst& call_inst);
265f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
266f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* Expand_OptArrayLength(llvm::CallInst& call_inst);
267f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* Expand_NewArray(llvm::CallInst& call_inst);
268f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* Expand_HLFilledNewArray(llvm::CallInst& call_inst);
269f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  void Expand_HLFillArrayData(llvm::CallInst& call_inst);
270f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
271f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* EmitAllocNewArray(uint32_t dex_pc,
272f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                 llvm::Value* array_length_value,
273f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                 uint32_t type_idx,
274f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                 bool is_filled_new_array);
275f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
276f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
277920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa                                                        art::InvokeType invoke_type,
278f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                                        llvm::Value* this_addr,
279f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                                        uint32_t dex_pc,
280f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                                        bool is_fast_path);
281f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2825e869b6560f918837cc6be3a50234deb2be46385TDYa  void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
2835e869b6560f918837cc6be3a50234deb2be46385TDYa
2845e869b6560f918837cc6be3a50234deb2be46385TDYa  void EmitUpdateDexPC(uint32_t dex_pc);
2855e869b6560f918837cc6be3a50234deb2be46385TDYa
2865e869b6560f918837cc6be3a50234deb2be46385TDYa  void EmitGuard_DivZeroException(uint32_t dex_pc,
2875e869b6560f918837cc6be3a50234deb2be46385TDYa                                  llvm::Value* denominator,
2885e869b6560f918837cc6be3a50234deb2be46385TDYa                                  JType op_jty);
2895e869b6560f918837cc6be3a50234deb2be46385TDYa
2905e869b6560f918837cc6be3a50234deb2be46385TDYa  void EmitGuard_NullPointerException(uint32_t dex_pc,
2915e869b6560f918837cc6be3a50234deb2be46385TDYa                                      llvm::Value* object);
2925e869b6560f918837cc6be3a50234deb2be46385TDYa
2935e869b6560f918837cc6be3a50234deb2be46385TDYa  void EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
2945e869b6560f918837cc6be3a50234deb2be46385TDYa                                                llvm::Value* array,
2955e869b6560f918837cc6be3a50234deb2be46385TDYa                                                llvm::Value* index);
2965e869b6560f918837cc6be3a50234deb2be46385TDYa
2975e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::FunctionType* GetFunctionType(uint32_t method_idx, bool is_static);
2985e869b6560f918837cc6be3a50234deb2be46385TDYa
2995e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
3005e869b6560f918837cc6be3a50234deb2be46385TDYa
3015e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::BasicBlock* CreateBasicBlockWithDexPC(uint32_t dex_pc,
3025e869b6560f918837cc6be3a50234deb2be46385TDYa                                              const char* postfix);
3035e869b6560f918837cc6be3a50234deb2be46385TDYa
3045e869b6560f918837cc6be3a50234deb2be46385TDYa  int32_t GetTryItemOffset(uint32_t dex_pc);
3055e869b6560f918837cc6be3a50234deb2be46385TDYa
3065e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::BasicBlock* GetLandingPadBasicBlock(uint32_t dex_pc);
3075e869b6560f918837cc6be3a50234deb2be46385TDYa
3085e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::BasicBlock* GetUnwindBasicBlock();
3095e869b6560f918837cc6be3a50234deb2be46385TDYa
3105e869b6560f918837cc6be3a50234deb2be46385TDYa  void EmitGuard_ExceptionLandingPad(uint32_t dex_pc);
3115e869b6560f918837cc6be3a50234deb2be46385TDYa
3125e869b6560f918837cc6be3a50234deb2be46385TDYa  void EmitBranchExceptionLandingPad(uint32_t dex_pc);
3135e869b6560f918837cc6be3a50234deb2be46385TDYa
31475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  //----------------------------------------------------------------------------
31575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  // Expand Arithmetic Helper Intrinsics
31675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  //----------------------------------------------------------------------------
31775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
31875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  llvm::Value* Expand_IntegerShift(llvm::Value* src1_value,
31975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                   llvm::Value* src2_value,
32075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                   IntegerShiftKind kind,
32175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                   JType op_jty);
32275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
32321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao public:
32421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  static char ID;
32521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
32621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb)
32721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
328e5b8f8b3eaef9871b8cea42cc8e98548754ac051Logan Chien        context_(irb.getContext()), rtb_(irb.Runtime()),
3298e950c117975d23f50ed7e32ca5db01a813c25d0TDYa        shadow_frame_(NULL), old_shadow_frame_(NULL),
330bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao        compiler_(NULL), dex_file_(NULL), code_item_(NULL),
33167645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien        oat_compilation_unit_(NULL), method_idx_(-1u), func_(NULL),
33267645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien        changed_(false)
33321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  { }
33421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
335bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
336920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa                  art::Compiler* compiler, art::OatCompilationUnit* oat_compilation_unit)
337bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao      : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
338bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao        context_(irb.getContext()), rtb_(irb.Runtime()),
3398e950c117975d23f50ed7e32ca5db01a813c25d0TDYa        shadow_frame_(NULL), old_shadow_frame_(NULL),
340bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao        compiler_(compiler),
341bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao        dex_file_(oat_compilation_unit->GetDexFile()),
342bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao        code_item_(oat_compilation_unit->GetCodeItem()),
343bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao        oat_compilation_unit_(oat_compilation_unit),
344bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao        method_idx_(oat_compilation_unit->GetDexMethodIndex()),
345bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao        func_(NULL), changed_(false)
346bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  { }
347bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao
34821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  bool runOnFunction(llvm::Function& func);
34921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
35021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao private:
35167645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  void InsertStackOverflowCheck(llvm::Function& func);
35221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
35321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
35421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                               llvm::CallInst& call_inst);
35521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
35621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao};
35721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
35821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaochar GBCExpanderPass::ID = 0;
35921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
36021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaobool GBCExpanderPass::runOnFunction(llvm::Function& func) {
361b672d1e48b6e02bb69c7cd9bcfa7509c81514c07TDYa  // Runtime support or stub
362b672d1e48b6e02bb69c7cd9bcfa7509c81514c07TDYa  if (func.getName().startswith("art_") || func.getName().startswith("Art")) {
363b672d1e48b6e02bb69c7cd9bcfa7509c81514c07TDYa    return false;
364b672d1e48b6e02bb69c7cd9bcfa7509c81514c07TDYa  }
36521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
36667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  // Setup rewrite context
36767645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  shadow_frame_ = NULL;
36867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  old_shadow_frame_ = NULL;
36967645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  func_ = &func;
37067645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  changed_ = false; // Assume unchanged
37121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
372c531cefbfb5394413122e9f57d211ba436cff012buzbee#if defined(ART_USE_PORTABLE_COMPILER)
373bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  basic_blocks_.resize(code_item_->insns_size_in_code_units_);
374bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  basic_block_landing_pads_.resize(code_item_->tries_size_, NULL);
375bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  basic_block_unwind_ = NULL;
376bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  for (llvm::Function::iterator bb_iter = func_->begin(), bb_end = func_->end();
377bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao       bb_iter != bb_end;
378bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao       ++bb_iter) {
379bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao    if (bb_iter->begin()->getMetadata("DexOff") == NULL) {
380bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao      continue;
381bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao    }
382bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao    uint32_t dex_pc = LV2UInt(bb_iter->begin()->getMetadata("DexOff")->getOperand(0));
383bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao    basic_blocks_[dex_pc] = bb_iter;
384bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  }
385bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao#endif
386bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao
38767645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  // Insert stack overflow check
38867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  InsertStackOverflowCheck(func); // TODO: Use intrinsic.
38921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
39067645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  // Rewrite the intrinsics
39167645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  RewriteFunction();
39221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
39367645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  VERIFY_LLVM_FUNCTION(func);
39421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
39567645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  return changed_;
39667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien}
39767645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
39867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chienvoid GBCExpanderPass::RewriteBasicBlock(llvm::BasicBlock* original_block) {
39967645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  llvm::BasicBlock* curr_basic_block = original_block;
40067645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
40167645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  llvm::BasicBlock::iterator inst_iter = original_block->begin();
40267645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  llvm::BasicBlock::iterator inst_end = original_block->end();
40367645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
40467645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  while (inst_iter != inst_end) {
40567645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst_iter);
40667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    IntrinsicHelper::IntrinsicId intr_id = IntrinsicHelper::UnknownId;
40767645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
40867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    if (call_inst) {
40967645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien      llvm::Function* callee_func = call_inst->getCalledFunction();
41067645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien      intr_id = intrinsic_helper_.GetIntrinsicId(callee_func);
41121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
41221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
41367645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    if (intr_id == IntrinsicHelper::UnknownId) {
41467645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien      // This is not intrinsic call.  Skip this instruction.
41567645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien      ++inst_iter;
41667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien      continue;
41767645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    }
41821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
41967645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    // Rewrite the intrinsic and change the function
42067645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    changed_ = true;
42167645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    irb_.SetInsertPoint(inst_iter);
42221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
42367645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    // Expand the intrinsic
42467645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    if (llvm::Value* new_value = ExpandIntrinsic(intr_id, *call_inst)) {
42567645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien      inst_iter->replaceAllUsesWith(new_value);
42667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    }
42721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
42867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    // Remove the old intrinsic call instruction
42967645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    llvm::BasicBlock::iterator old_inst = inst_iter++;
43067645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    old_inst->eraseFromParent();
43167645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
43267645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    // Splice the instruction to the new basic block
43367645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
43467645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    if (next_basic_block != curr_basic_block) {
43567645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien      next_basic_block->getInstList().splice(
43667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien          irb_.GetInsertPoint(), curr_basic_block->getInstList(),
43767645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien          inst_iter, inst_end);
43867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien      curr_basic_block = next_basic_block;
43967645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien      inst_end = curr_basic_block->end();
44067645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    }
44167645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  }
44267645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien}
44321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
44421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
44567645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chienvoid GBCExpanderPass::RewriteFunction() {
44667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  size_t num_basic_blocks = func_->getBasicBlockList().size();
44767645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  // NOTE: We are not using (bb_iter != bb_end) as the for-loop condition,
44867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  // because we will create new basic block while expanding the intrinsics.
44967645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  // We only want to iterate through the input basic blocks.
45021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
451aa55887fd30484a77e7775dfbcddbee883ce6380TDYa  landing_pad_phi_mapping_.clear();
452aa55887fd30484a77e7775dfbcddbee883ce6380TDYa
45367645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  for (llvm::Function::iterator bb_iter = func_->begin();
45467645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien       num_basic_blocks > 0; ++bb_iter, --num_basic_blocks) {
455627d8c4ae50f22f628fe6a768f2924ee7e0029deShih-wei Liao    // Set insert point to current basic block.
456627d8c4ae50f22f628fe6a768f2924ee7e0029deShih-wei Liao    irb_.SetInsertPoint(bb_iter);
45767645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
45855e5e6c5702e3f1f68bd83ae741af769740d9a74TDYa    current_bb_ = bb_iter;
459aa55887fd30484a77e7775dfbcddbee883ce6380TDYa
46067645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    // Rewrite the basic block
46167645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    RewriteBasicBlock(bb_iter);
46267645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
46367645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    // Update the phi-instructions in the successor basic block
46467645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    llvm::BasicBlock* last_block = irb_.GetInsertBlock();
46567645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    if (last_block != bb_iter) {
46667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien      UpdatePhiInstruction(bb_iter, last_block);
46721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
46867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  }
469aa55887fd30484a77e7775dfbcddbee883ce6380TDYa
470aa55887fd30484a77e7775dfbcddbee883ce6380TDYa  typedef std::map<llvm::PHINode*, llvm::PHINode*> HandlerPHIMap;
471aa55887fd30484a77e7775dfbcddbee883ce6380TDYa  HandlerPHIMap handler_phi;
472aa55887fd30484a77e7775dfbcddbee883ce6380TDYa  // Iterate every used landing pad basic block
473aa55887fd30484a77e7775dfbcddbee883ce6380TDYa  for (size_t i = 0, ei = basic_block_landing_pads_.size(); i != ei; ++i) {
474aa55887fd30484a77e7775dfbcddbee883ce6380TDYa    llvm::BasicBlock* lbb = basic_block_landing_pads_[i];
475aa55887fd30484a77e7775dfbcddbee883ce6380TDYa    if (lbb == NULL) {
476aa55887fd30484a77e7775dfbcddbee883ce6380TDYa      continue;
477aa55887fd30484a77e7775dfbcddbee883ce6380TDYa    }
478aa55887fd30484a77e7775dfbcddbee883ce6380TDYa
479aa55887fd30484a77e7775dfbcddbee883ce6380TDYa    llvm::TerminatorInst* term_inst = lbb->getTerminator();
480aa55887fd30484a77e7775dfbcddbee883ce6380TDYa    std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*> >& rewrite_pair
481aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        = landing_pad_phi_mapping_[lbb];
482aa55887fd30484a77e7775dfbcddbee883ce6380TDYa    irb_.SetInsertPoint(lbb->begin());
483aa55887fd30484a77e7775dfbcddbee883ce6380TDYa
484aa55887fd30484a77e7775dfbcddbee883ce6380TDYa    // Iterate every succeeding basic block (catch block)
485aa55887fd30484a77e7775dfbcddbee883ce6380TDYa    for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
486aa55887fd30484a77e7775dfbcddbee883ce6380TDYa         succ_iter != succ_end; ++succ_iter) {
487aa55887fd30484a77e7775dfbcddbee883ce6380TDYa      llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
488aa55887fd30484a77e7775dfbcddbee883ce6380TDYa
489aa55887fd30484a77e7775dfbcddbee883ce6380TDYa      // Iterate every phi instructions in the succeeding basic block
490aa55887fd30484a77e7775dfbcddbee883ce6380TDYa      for (llvm::BasicBlock::iterator
491aa55887fd30484a77e7775dfbcddbee883ce6380TDYa           inst_iter = succ_basic_block->begin(),
492aa55887fd30484a77e7775dfbcddbee883ce6380TDYa           inst_end = succ_basic_block->end();
493aa55887fd30484a77e7775dfbcddbee883ce6380TDYa           inst_iter != inst_end; ++inst_iter) {
494aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
495aa55887fd30484a77e7775dfbcddbee883ce6380TDYa
496aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        if (!phi) {
497aa55887fd30484a77e7775dfbcddbee883ce6380TDYa          break; // Meet non-phi instruction.  Done.
498aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        }
499aa55887fd30484a77e7775dfbcddbee883ce6380TDYa
500aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        if (handler_phi[phi] == NULL) {
501aa55887fd30484a77e7775dfbcddbee883ce6380TDYa          handler_phi[phi] = llvm::PHINode::Create(phi->getType(), 1);
502aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        }
503aa55887fd30484a77e7775dfbcddbee883ce6380TDYa
504aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        // Create new_phi in landing pad
505aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        llvm::PHINode* new_phi = irb_.CreatePHI(phi->getType(), rewrite_pair.size());
506aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        // Insert all incoming value into new_phi by rewrite_pair
507aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
508aa55887fd30484a77e7775dfbcddbee883ce6380TDYa          llvm::BasicBlock* old_bb = rewrite_pair[j].first;
509aa55887fd30484a77e7775dfbcddbee883ce6380TDYa          llvm::BasicBlock* new_bb = rewrite_pair[j].second;
510aa55887fd30484a77e7775dfbcddbee883ce6380TDYa          new_phi->addIncoming(phi->getIncomingValueForBlock(old_bb), new_bb);
511aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        }
512aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        // Delete all incoming value from phi by rewrite_pair
513aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
514aa55887fd30484a77e7775dfbcddbee883ce6380TDYa          llvm::BasicBlock* old_bb = rewrite_pair[j].first;
515aa55887fd30484a77e7775dfbcddbee883ce6380TDYa          int old_bb_idx = phi->getBasicBlockIndex(old_bb);
516aa55887fd30484a77e7775dfbcddbee883ce6380TDYa          if (old_bb_idx >= 0) {
517aa55887fd30484a77e7775dfbcddbee883ce6380TDYa            phi->removeIncomingValue(old_bb_idx, false);
518aa55887fd30484a77e7775dfbcddbee883ce6380TDYa          }
519aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        }
520aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        // Insert new_phi into new handler phi
521aa55887fd30484a77e7775dfbcddbee883ce6380TDYa        handler_phi[phi]->addIncoming(new_phi, lbb);
522aa55887fd30484a77e7775dfbcddbee883ce6380TDYa      }
523aa55887fd30484a77e7775dfbcddbee883ce6380TDYa    }
524aa55887fd30484a77e7775dfbcddbee883ce6380TDYa  }
525aa55887fd30484a77e7775dfbcddbee883ce6380TDYa
526aa55887fd30484a77e7775dfbcddbee883ce6380TDYa  // Replace all handler phi
527aa55887fd30484a77e7775dfbcddbee883ce6380TDYa  // We can't just use the old handler phi, because some exception edges will disappear after we
528aa55887fd30484a77e7775dfbcddbee883ce6380TDYa  // compute fast-path.
529aa55887fd30484a77e7775dfbcddbee883ce6380TDYa  for (HandlerPHIMap::iterator it = handler_phi.begin(); it != handler_phi.end(); ++it) {
530aa55887fd30484a77e7775dfbcddbee883ce6380TDYa    llvm::PHINode* old_phi = it->first;
531aa55887fd30484a77e7775dfbcddbee883ce6380TDYa    llvm::PHINode* new_phi = it->second;
532aa55887fd30484a77e7775dfbcddbee883ce6380TDYa    new_phi->insertBefore(old_phi);
533aa55887fd30484a77e7775dfbcddbee883ce6380TDYa    old_phi->replaceAllUsesWith(new_phi);
534aa55887fd30484a77e7775dfbcddbee883ce6380TDYa    old_phi->eraseFromParent();
535aa55887fd30484a77e7775dfbcddbee883ce6380TDYa  }
53667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien}
53721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
53867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chienvoid GBCExpanderPass::UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
53967645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien                                           llvm::BasicBlock* new_basic_block) {
54067645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  llvm::TerminatorInst* term_inst = new_basic_block->getTerminator();
54167645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
54267645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  if (!term_inst) {
54367645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    return; // No terminating instruction in new_basic_block.  Nothing to do.
54421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  }
54521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
54667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  // Iterate every succeeding basic block
54767645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
54867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien       succ_iter != succ_end; ++succ_iter) {
54967645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
55067645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
55167645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    // Iterate every phi instructions in the succeeding basic block
55267645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    for (llvm::BasicBlock::iterator
55367645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien         inst_iter = succ_basic_block->begin(),
55467645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien         inst_end = succ_basic_block->end();
55567645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien         inst_iter != inst_end; ++inst_iter) {
55667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien      llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
55721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
55867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien      if (!phi) {
55967645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien        break; // Meet non-phi instruction.  Done.
56067645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien      }
56167645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
56267645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien      // Update the incoming block of this phi instruction
56367645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien      for (llvm::PHINode::block_iterator
56467645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien           ibb_iter = phi->block_begin(), ibb_end = phi->block_end();
56567645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien           ibb_iter != ibb_end; ++ibb_iter) {
56667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien        if (*ibb_iter == old_basic_block) {
56767645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien          *ibb_iter = new_basic_block;
56867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien        }
56921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      }
57021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
57121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  }
57221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
57321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
57421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value* GBCExpanderPass::ExpandToRuntime(runtime_support::RuntimeId rt,
57521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                              llvm::CallInst& inst) {
57621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
57721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // the arguments passed to the GBC intrinsic are as the same as IBC runtime
57821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // function, therefore only called function is needed to change.
57921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  unsigned num_args = inst.getNumArgOperands();
58021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
58121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  if (num_args <= 0) {
58221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    return irb_.CreateCall(irb_.GetRuntime(rt));
58321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  } else {
58421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    std::vector<llvm::Value*> args;
58521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    for (unsigned i = 0; i < num_args; i++) {
58621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      args.push_back(inst.getArgOperand(i));
58721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
58821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
58921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    return irb_.CreateCall(irb_.GetRuntime(rt), args);
59021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  }
59121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
59221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
59367645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chienvoid
59421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei LiaoGBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
59521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Function* func = first_non_alloca->getParent()->getParent();
59621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Module* module = func->getParent();
59721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
59821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Call llvm intrinsic function to get frame address.
59921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Function* frameaddress =
60021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
60121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
60221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
60321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
60421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
60521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Cast i8* to int
60621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
60721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
60821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Get thread.stack_end_
60921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* stack_end =
610920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::StackEndOffset().Int32Value(),
61121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                            irb_.getPtrEquivIntTy(),
61221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                            kTBAARuntimeInfo);
61321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
61421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Check the frame address < thread.stack_end_ ?
61521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
61621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
61721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::BasicBlock* block_exception =
61821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      llvm::BasicBlock::Create(context_, "stack_overflow", func);
61921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
62021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::BasicBlock* block_continue =
62121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
62221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
62321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
62421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
62521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // If stack overflow, throw exception.
62621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.SetInsertPoint(block_exception);
62721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowStackOverflowException));
62821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
62921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Unwind.
63021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Type* ret_type = func->getReturnType();
63121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  if (ret_type->isVoidTy()) {
63221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.CreateRetVoid();
63321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  } else {
63421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    // The return value is ignored when there's an exception. MethodCompiler
63521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    // returns zero value under the the corresponding return type  in this case.
63621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    // GBCExpander returns LLVM undef value here for brevity
63721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.CreateRet(llvm::UndefValue::get(ret_type));
63821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  }
63921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
64021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.SetInsertPoint(block_continue);
64121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
64221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
643920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYallvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(art::MemberOffset offset) {
64421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
64521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
64621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return irb_.LoadFromObjectOffset(method_object_addr,
64721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                   offset.Int32Value(),
64821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                   irb_.getJObjectTy(),
64921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                   kTBAAConstJObject);
65021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
65121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
65221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value*
65321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei LiaoGBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
65421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* static_storage_dex_cache_addr =
65566f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier    EmitLoadDexCacheAddr(art::AbstractMethod::DexCacheInitializedStaticStorageOffset());
65621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
65721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
65821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
65921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
66021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
66121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
66221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value*
66321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei LiaoGBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
66421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* resolved_type_dex_cache_addr =
66566f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier    EmitLoadDexCacheAddr(art::AbstractMethod::DexCacheResolvedTypesOffset());
66621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
66721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
66821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
66921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
67021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
67121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
67221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value* GBCExpanderPass::
67321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei LiaoEmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
67421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* resolved_method_dex_cache_addr =
67566f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier    EmitLoadDexCacheAddr(art::AbstractMethod::DexCacheResolvedMethodsOffset());
67621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
67721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
67821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
67921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
68021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
68121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
68221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value* GBCExpanderPass::
68321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei LiaoEmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
68421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* string_dex_cache_addr =
68566f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier    EmitLoadDexCacheAddr(art::AbstractMethod::DexCacheStringsOffset());
68621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
68721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
68821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
68921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
69021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
69121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
69221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
69321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
69421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return parent_func->arg_begin();
69521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
69621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
69721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
69821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Load array length
69921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return irb_.LoadFromObjectOffset(array,
700920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa                                   art::Array::LengthOffset().Int32Value(),
70121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                   irb_.getJIntTy(),
70221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                   kTBAAConstJObject);
70321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
70421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
70521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
70621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value*
70721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei LiaoGBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
70821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* callee_method_object_field_addr =
70921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
71021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
711ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  return irb_.CreateLoad(callee_method_object_field_addr, kTBAARuntimeInfo);
71221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
71321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
71421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value* GBCExpanderPass::
71521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei LiaoEmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
71621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Load class object of *this* pointer
71721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* class_object_addr =
71821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.LoadFromObjectOffset(this_addr,
719920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa                              art::Object::ClassOffset().Int32Value(),
72021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                              irb_.getJObjectTy(),
72121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                              kTBAAConstJObject);
72221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
72321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Load vtable address
72421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* vtable_addr =
72521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.LoadFromObjectOffset(class_object_addr,
726920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa                              art::Class::VTableOffset().Int32Value(),
72721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                              irb_.getJObjectTy(),
72821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                              kTBAAConstJObject);
72921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
73021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Load callee method object
73121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* vtable_idx_value =
73221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
73321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
73421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* method_field_addr =
73521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
73621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
73721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
73821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
73921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
74021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao// Emit Array GetElementPtr
74121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
74221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                           llvm::Value* index_value,
74321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                           JType elem_jty) {
74421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
74521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  int data_offset;
74621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  if (elem_jty == kLong || elem_jty == kDouble ||
747920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa      (elem_jty == kObject && sizeof(uint64_t) == sizeof(art::Object*))) {
748920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    data_offset = art::Array::DataOffset(sizeof(int64_t)).Int32Value();
74921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  } else {
750920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    data_offset = art::Array::DataOffset(sizeof(int32_t)).Int32Value();
75121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  }
75221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
75321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Constant* data_offset_value =
75421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.getPtrEquivInt(data_offset);
75521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
75621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Type* elem_type = irb_.getJType(elem_jty, kArray);
75721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
75821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* array_data_addr =
75921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.CreatePtrDisp(array_addr, data_offset_value,
76021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                       elem_type->getPointerTo());
76121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
76221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return irb_.CreateGEP(array_data_addr, index_value);
76321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
76421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
76521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaovoid GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
766ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
767ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa
768ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  llvm::Value* suspend_count =
769ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa      irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::ThreadFlagsOffset().Int32Value(),
770ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa                                              irb_.getInt16Ty(),
771ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa                                              kTBAARuntimeInfo);
772ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  llvm::Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
773ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa
774ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  llvm::BasicBlock* basic_block_suspend = CreateBasicBlockWithDexPC(dex_pc, "suspend");
775ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  llvm::BasicBlock* basic_block_cont = CreateBasicBlockWithDexPC(dex_pc, "suspend_cont");
776ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa
777ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
778ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa
779ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  irb_.SetInsertPoint(basic_block_suspend);
780ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  if (dex_pc != art::DexFile::kDexNoIndex) {
781ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa    EmitUpdateDexPC(dex_pc);
782ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  }
78321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.Runtime().EmitTestSuspend();
784ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  irb_.CreateBr(basic_block_cont);
785ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa
786ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  irb_.SetInsertPoint(basic_block_cont);
78721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return;
78821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
78921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
7909a129457c233b653c7a8f65c963509267252b0a7TDYavoid GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
7919a129457c233b653c7a8f65c963509267252b0a7TDYa  irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
7929a129457c233b653c7a8f65c963509267252b0a7TDYa  return;
7939a129457c233b653c7a8f65c963509267252b0a7TDYa}
7949a129457c233b653c7a8f65c963509267252b0a7TDYa
79521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value*
79621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei LiaoGBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
79721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  uint32_t string_idx =
79821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
79921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
80021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
80121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
802ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  return irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
80321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
80421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
80521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value*
80621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei LiaoGBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
80721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  uint32_t type_idx =
80821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
80921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
81021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* type_field_addr =
81121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
81221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
813ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  return irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
81421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
81521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
81621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaovoid GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
81721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  rtb_.EmitLockObject(obj);
81821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return;
81921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
82021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
82121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaovoid GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
82221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  rtb_.EmitUnlockObject(obj);
82321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return;
82421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
82521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
82621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
82721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                              llvm::Value* index_value,
82821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                              JType elem_jty) {
82921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* array_elem_addr =
83021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    EmitArrayGEP(array_addr, index_value, elem_jty);
83121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
83221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
83321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
83421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
83521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaovoid GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
83621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                      llvm::Value* array_addr,
83721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                      llvm::Value* index_value,
83821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                      JType elem_jty) {
83921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* array_elem_addr =
84021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    EmitArrayGEP(array_addr, index_value, elem_jty);
84121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
84221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
84321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
84421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return;
84521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
84621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
84721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaovoid GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
84821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
84921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* array = call_inst.getArgOperand(0);
85021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
85121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  uint32_t element_jty =
85221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
85321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
85421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  DCHECK(call_inst.getNumArgOperands() > 2);
85521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  unsigned num_elements = (call_inst.getNumArgOperands() - 2);
85621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
85721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
85821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
85921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  uint32_t alignment;
86021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Constant* elem_size;
86121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::PointerType* field_type;
86221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
86321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
86421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // as the element, thus we are only checking 2 cases: primitive int and
86521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // non-primitive type.
86621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  if (is_elem_int_ty) {
86721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    alignment = sizeof(int32_t);
86821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
86921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    field_type = irb_.getJIntTy()->getPointerTo();
87021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  } else {
87121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    alignment = irb_.getSizeOfPtrEquivInt();
87221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    elem_size = irb_.getSizeOfPtrEquivIntValue();
87321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    field_type = irb_.getJObjectTy()->getPointerTo();
87421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  }
87521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
87621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* data_field_offset =
877920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    irb_.getPtrEquivInt(art::Array::DataOffset(alignment).Int32Value());
87821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
87921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* data_field_addr =
88021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.CreatePtrDisp(array, data_field_offset, field_type);
88121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
88221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  for (unsigned i = 0; i < num_elements; ++i) {
88321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    // Values to fill the array begin at the 3rd argument
88421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
88521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
88621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
88721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
88821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    data_field_addr =
88921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
89021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  }
89121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
89221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return;
89321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
89421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
89521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
89621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                              llvm::Value* /*is_volatile_value*/,
89721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                              llvm::Value* object_addr,
89821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                              JType field_jty) {
89921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  int field_offset =
90021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
90121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
90221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  DCHECK_GE(field_offset, 0);
90321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
90421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::PointerType* field_type =
90521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.getJType(field_jty, kField)->getPointerTo();
90621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
90721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  field_offset_value = irb_.getPtrEquivInt(field_offset);
90821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
90921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* field_addr =
91021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
91121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
91221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // TODO: Check is_volatile.  We need to generate atomic load instruction
91321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // when is_volatile is true.
91421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
91521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
91621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
91721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaovoid GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
91821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                      llvm::Value* /* is_volatile_value */,
91921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                      llvm::Value* object_addr,
92021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                      llvm::Value* new_value,
92121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                      JType field_jty) {
92221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  int field_offset =
92321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
92421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
92521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  DCHECK_GE(field_offset, 0);
92621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
92721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::PointerType* field_type =
92821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.getJType(field_jty, kField)->getPointerTo();
92921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
93021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  field_offset_value = irb_.getPtrEquivInt(field_offset);
93121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
93221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* field_addr =
93321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
93421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
93521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // TODO: Check is_volatile.  We need to generate atomic store instruction
93621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // when is_volatile is true.
93721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
93821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
93921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return;
94021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
94121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
94221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
94321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                              llvm::Value* field_offset_value,
94421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                              llvm::Value* /*is_volatile_value*/,
94521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                              JType field_jty) {
94621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  int field_offset =
94721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
94821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
94921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  DCHECK_GE(field_offset, 0);
95021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
95121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
95221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
95321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* static_field_addr =
95421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
95521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                       irb_.getJType(field_jty, kField)->getPointerTo());
95621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
95721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // TODO: Check is_volatile.  We need to generate atomic store instruction
95821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // when is_volatile is true.
95921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
96021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
96121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
96221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaovoid GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
96321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                      llvm::Value* field_offset_value,
96421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                      llvm::Value* /* is_volatile_value */,
96521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                      llvm::Value* new_value,
96621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                      JType field_jty) {
96721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  int field_offset =
96821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
96921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
97021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  DCHECK_GE(field_offset, 0);
97121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
97221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
97321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
97421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* static_field_addr =
97521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
97621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                       irb_.getJType(field_jty, kField)->getPointerTo());
97721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
97821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // TODO: Check is_volatile.  We need to generate atomic store instruction
97921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // when is_volatile is true.
98021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
98121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
98221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return;
98321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
98421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
98521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value*
98621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei LiaoGBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
98721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return irb_.LoadFromObjectOffset(method_object_addr,
98866f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier                                   art::AbstractMethod::DeclaringClassOffset().Int32Value(),
98921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                   irb_.getJObjectTy(),
99021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                   kTBAAConstJObject);
99121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
99221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
99321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value*
99421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei LiaoGBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
99521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  uint32_t type_idx =
99621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
99721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
99821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* storage_field_addr =
99921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
100021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
1001ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  return irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
100221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
100321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
100421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value*
100521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei LiaoGBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
100621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  uint32_t callee_method_idx =
100721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
100821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
100921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
101021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
101121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
101221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
101321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    llvm::Value* vtable_idx_value,
101421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    llvm::Value* this_addr) {
101521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  int vtable_idx =
101621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
101721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
101821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
101921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
102021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
102121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
102221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
102321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
102421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  unsigned num_args = call_inst.getNumArgOperands();
102521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Type* ret_type = call_inst.getType();
102621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
102721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Determine the function type of the callee method
102821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  std::vector<llvm::Type*> args_type;
102921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  std::vector<llvm::Value*> args;
103021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  for (unsigned i = 0; i < num_args; i++) {
103121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    args.push_back(call_inst.getArgOperand(i));
103221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    args_type.push_back(args[i]->getType());
103321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  }
103421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
103521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::FunctionType* callee_method_type =
103621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    llvm::FunctionType::get(ret_type, args_type, false);
103721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
103821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* code_addr =
103921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.LoadFromObjectOffset(callee_method_object_addr,
104066f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier                              art::AbstractMethod::GetCodeOffset().Int32Value(),
104121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                              callee_method_type->getPointerTo(),
1042ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa                              kTBAARuntimeInfo);
104321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
104421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Invoke callee
104521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* retval = irb_.CreateCall(code_addr, args);
104621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
104721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return retval;
104821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
104921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
10504ec8ccdaeee1c4af1a70e1ac0dd482e83df72f38TDYallvm::Value* GBCExpanderPass::Expand_DivRem(llvm::CallInst& call_inst,
105121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                            bool is_div, JType op_jty) {
10524ec8ccdaeee1c4af1a70e1ac0dd482e83df72f38TDYa  llvm::Value* dividend = call_inst.getArgOperand(0);
10534ec8ccdaeee1c4af1a70e1ac0dd482e83df72f38TDYa  llvm::Value* divisor = call_inst.getArgOperand(1);
1054c531cefbfb5394413122e9f57d211ba436cff012buzbee#if defined(ART_USE_PORTABLE_COMPILER)
10554ec8ccdaeee1c4af1a70e1ac0dd482e83df72f38TDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
10564ec8ccdaeee1c4af1a70e1ac0dd482e83df72f38TDYa  EmitGuard_DivZeroException(dex_pc, divisor, op_jty);
10574ec8ccdaeee1c4af1a70e1ac0dd482e83df72f38TDYa#endif
105821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
105921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
106021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Check the special case: MININT / -1 = MININT
106121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // That case will cause overflow, which is undefined behavior in llvm.
106221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // So we check the divisor is -1 or not, if the divisor is -1, we do
106321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // the special path to avoid undefined behavior.
106421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Type* op_type = irb_.getJType(op_jty, kAccurate);
106521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* zero = irb_.getJZero(op_jty);
106621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
106721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
10685e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::Function* parent = irb_.GetInsertBlock()->getParent();
106921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
107021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
107121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::BasicBlock* neg_one_cont =
107221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    llvm::BasicBlock::Create(context_, "", parent);
107321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
107421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
107521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
107621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
107721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // If divisor == -1
107821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.SetInsertPoint(eq_neg_one);
107921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* eq_result;
108021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  if (is_div) {
108121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    // We can just change from "dividend div -1" to "neg dividend". The sub
108221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    // don't care the sign/unsigned because of two's complement representation.
108321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    // And the behavior is what we want:
108421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    //  -(2^n)        (2^n)-1
108521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    //  MININT  < k <= MAXINT    ->     mul k -1  =  -k
108621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    //  MININT == k              ->     mul k -1  =   k
108721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    //
108821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    // LLVM use sub to represent 'neg'
108921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    eq_result = irb_.CreateSub(zero, dividend);
109021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  } else {
109121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    // Everything modulo -1 will be 0.
109221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    eq_result = zero;
109321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  }
109421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.CreateBr(neg_one_cont);
109521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
109621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // If divisor != -1, just do the division.
109721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.SetInsertPoint(ne_neg_one);
109821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* ne_result;
109921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  if (is_div) {
110021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    ne_result = irb_.CreateSDiv(dividend, divisor);
110121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  } else {
110221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    ne_result = irb_.CreateSRem(dividend, divisor);
110321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  }
110421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.CreateBr(neg_one_cont);
110521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
110621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.SetInsertPoint(neg_one_cont);
110721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
110821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  result->addIncoming(eq_result, eq_neg_one);
110921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  result->addIncoming(ne_result, ne_neg_one);
111021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
111121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return result;
111221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
111321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
1114ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYavoid GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_vregs_value) {
111521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
111621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // MethodCompiler::EmitPushShadowFrame
11178e950c117975d23f50ed7e32ca5db01a813c25d0TDYa  uint16_t num_vregs =
11188e950c117975d23f50ed7e32ca5db01a813c25d0TDYa    llvm::cast<llvm::ConstantInt>(num_vregs_value)->getZExtValue();
111921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
112021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::StructType* shadow_frame_type =
1121ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa    irb_.getShadowFrameTy(num_vregs);
112221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
112321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
112421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
112521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Alloca a pointer to old shadow frame
112621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  old_shadow_frame_ =
112721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
112821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
112921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Push the shadow frame
113021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
113121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
113221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* shadow_frame_upcast =
113321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
113421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
113521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
113621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                                 method_object_addr,
11378e950c117975d23f50ed7e32ca5db01a813c25d0TDYa                                                 num_vregs);
113821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
113921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
114021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
114121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return;
114221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
114321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
11448e950c117975d23f50ed7e32ca5db01a813c25d0TDYavoid GBCExpanderPass::Expand_SetVReg(llvm::Value* entry_idx,
11458e950c117975d23f50ed7e32ca5db01a813c25d0TDYa                                     llvm::Value* value) {
11468e950c117975d23f50ed7e32ca5db01a813c25d0TDYa  DCHECK(shadow_frame_ != NULL);
11478e950c117975d23f50ed7e32ca5db01a813c25d0TDYa
11488e950c117975d23f50ed7e32ca5db01a813c25d0TDYa  llvm::Value* gep_index[] = {
11498e950c117975d23f50ed7e32ca5db01a813c25d0TDYa    irb_.getInt32(0), // No pointer displacement
1150ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa    irb_.getInt32(1), // VRegs
11518e950c117975d23f50ed7e32ca5db01a813c25d0TDYa    entry_idx // Pointer field
11528e950c117975d23f50ed7e32ca5db01a813c25d0TDYa  };
11538e950c117975d23f50ed7e32ca5db01a813c25d0TDYa
11548e950c117975d23f50ed7e32ca5db01a813c25d0TDYa  llvm::Value* vreg_addr = irb_.CreateGEP(shadow_frame_, gep_index);
11558e950c117975d23f50ed7e32ca5db01a813c25d0TDYa
11568e950c117975d23f50ed7e32ca5db01a813c25d0TDYa  irb_.CreateStore(value,
11578e950c117975d23f50ed7e32ca5db01a813c25d0TDYa                   irb_.CreateBitCast(vreg_addr, value->getType()->getPointerTo()),
11588e950c117975d23f50ed7e32ca5db01a813c25d0TDYa                   kTBAAShadowFrame);
11598e950c117975d23f50ed7e32ca5db01a813c25d0TDYa  return;
11608e950c117975d23f50ed7e32ca5db01a813c25d0TDYa}
11618e950c117975d23f50ed7e32ca5db01a813c25d0TDYa
116221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaovoid GBCExpanderPass::Expand_PopShadowFrame() {
1163c531cefbfb5394413122e9f57d211ba436cff012buzbee#if defined(ART_USE_PORTABLE_COMPILER)
1164bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  if (old_shadow_frame_ == NULL) {
1165bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao    return;
1166bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  }
1167bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao#endif
116821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
116921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return;
117021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
117121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
117221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaovoid GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
117321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  irb_.StoreToObjectOffset(shadow_frame_,
1174920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa                           art::ShadowFrame::DexPCOffset(),
117521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                           dex_pc_value,
117621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                           kTBAAShadowFrame);
117721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return;
117821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
117921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
118067645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chienvoid GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
11814028312f6f4b49fd69992daf28cd37dd32e79a47jeffhao  // All alloca instructions are generated in the first basic block of the
11824028312f6f4b49fd69992daf28cd37dd32e79a47jeffhao  // function, and there are no alloca instructions after the first non-alloca
11834028312f6f4b49fd69992daf28cd37dd32e79a47jeffhao  // instruction.
118421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
118567645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  llvm::BasicBlock* first_basic_block = &func.front();
118667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
118767645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  // Look for first non-alloca instruction
118867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  llvm::BasicBlock::iterator first_non_alloca = first_basic_block->begin();
118921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
119021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    ++first_non_alloca;
119121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  }
119221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
119367645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  irb_.SetInsertPoint(first_non_alloca);
119467645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
119521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // Insert stack overflow check codes before first_non_alloca (i.e., after all
119621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  // alloca instructions)
119767645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  EmitStackOverflowCheck(&*first_non_alloca);
119867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
1199c531cefbfb5394413122e9f57d211ba436cff012buzbee#if defined(ART_USE_PORTABLE_COMPILER)
1200890ea89879ba555a08433146058d516575646c59TDYa  irb_.Runtime().EmitTestSuspend();
1201890ea89879ba555a08433146058d516575646c59TDYa#endif
1202890ea89879ba555a08433146058d516575646c59TDYa
120367645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
120467645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  if (next_basic_block != first_basic_block) {
120567645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    // Splice the rest of the instruction to the continuing basic block
120667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    next_basic_block->getInstList().splice(
120767645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien        irb_.GetInsertPoint(), first_basic_block->getInstList(),
120867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien        first_non_alloca, first_basic_block->end());
120967645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
121067645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    // Rewrite the basic block
121167645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    RewriteBasicBlock(next_basic_block);
121267645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
121367645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    // Update the phi-instructions in the successor basic block
121467645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien    UpdatePhiInstruction(first_basic_block, irb_.GetInsertBlock());
121567645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  }
121667645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien
121767645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  // We have changed the basic block
121867645d87ea0367b9601e7967fa8809e4be9bde7cLogan Chien  changed_ = true;
121921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
122021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
12215e869b6560f918837cc6be3a50234deb2be46385TDYa// ==== High-level intrinsic expander ==========================================
12225e869b6560f918837cc6be3a50234deb2be46385TDYa
1223a1b2185820e6080864d18a35759cc046dc4ee578TDYallvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
1224a1b2185820e6080864d18a35759cc046dc4ee578TDYa                                               llvm::Value* src2_value,
1225a1b2185820e6080864d18a35759cc046dc4ee578TDYa                                               bool gt_bias) {
1226a1b2185820e6080864d18a35759cc046dc4ee578TDYa  llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
1227a1b2185820e6080864d18a35759cc046dc4ee578TDYa  llvm::Value* cmp_lt;
1228a1b2185820e6080864d18a35759cc046dc4ee578TDYa
1229a1b2185820e6080864d18a35759cc046dc4ee578TDYa  if (gt_bias) {
1230a1b2185820e6080864d18a35759cc046dc4ee578TDYa    cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
1231a1b2185820e6080864d18a35759cc046dc4ee578TDYa  } else {
1232a1b2185820e6080864d18a35759cc046dc4ee578TDYa    cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
1233a1b2185820e6080864d18a35759cc046dc4ee578TDYa  }
1234a1b2185820e6080864d18a35759cc046dc4ee578TDYa
1235a1b2185820e6080864d18a35759cc046dc4ee578TDYa  return EmitCompareResultSelection(cmp_eq, cmp_lt);
1236a1b2185820e6080864d18a35759cc046dc4ee578TDYa}
1237a1b2185820e6080864d18a35759cc046dc4ee578TDYa
1238a1b2185820e6080864d18a35759cc046dc4ee578TDYallvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
1239a1b2185820e6080864d18a35759cc046dc4ee578TDYa  llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
1240a1b2185820e6080864d18a35759cc046dc4ee578TDYa  llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
1241a1b2185820e6080864d18a35759cc046dc4ee578TDYa
1242a1b2185820e6080864d18a35759cc046dc4ee578TDYa  return EmitCompareResultSelection(cmp_eq, cmp_lt);
1243a1b2185820e6080864d18a35759cc046dc4ee578TDYa}
1244a1b2185820e6080864d18a35759cc046dc4ee578TDYa
1245a1b2185820e6080864d18a35759cc046dc4ee578TDYallvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
1246a1b2185820e6080864d18a35759cc046dc4ee578TDYa                                                         llvm::Value* cmp_lt) {
1247a1b2185820e6080864d18a35759cc046dc4ee578TDYa
1248a1b2185820e6080864d18a35759cc046dc4ee578TDYa  llvm::Constant* zero = irb_.getJInt(0);
1249a1b2185820e6080864d18a35759cc046dc4ee578TDYa  llvm::Constant* pos1 = irb_.getJInt(1);
1250a1b2185820e6080864d18a35759cc046dc4ee578TDYa  llvm::Constant* neg1 = irb_.getJInt(-1);
1251a1b2185820e6080864d18a35759cc046dc4ee578TDYa
1252a1b2185820e6080864d18a35759cc046dc4ee578TDYa  llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
1253a1b2185820e6080864d18a35759cc046dc4ee578TDYa  llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
1254a1b2185820e6080864d18a35759cc046dc4ee578TDYa
1255a1b2185820e6080864d18a35759cc046dc4ee578TDYa  return result_eq;
1256a1b2185820e6080864d18a35759cc046dc4ee578TDYa}
1257a1b2185820e6080864d18a35759cc046dc4ee578TDYa
125875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chienllvm::Value* GBCExpanderPass::Expand_IntegerShift(llvm::Value* src1_value,
125975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                                  llvm::Value* src2_value,
126075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                                  IntegerShiftKind kind,
126175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                                  JType op_jty) {
126275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  DCHECK(op_jty == kInt || op_jty == kLong);
126375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
126475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  // Mask and zero-extend RHS properly
126575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  if (op_jty == kInt) {
126675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    src2_value = irb_.CreateAnd(src2_value, 0x1f);
126775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  } else {
126875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    llvm::Value* masked_src2_value = irb_.CreateAnd(src2_value, 0x3f);
126975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    src2_value = irb_.CreateZExt(masked_src2_value, irb_.getJLongTy());
127075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  }
127175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
127275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  // Create integer shift llvm instruction
127375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  switch (kind) {
127475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  case kIntegerSHL:
127575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    return irb_.CreateShl(src1_value, src2_value);
127675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
127775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  case kIntegerSHR:
127875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    return irb_.CreateAShr(src1_value, src2_value);
127975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
128075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  case kIntegerUSHR:
128175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    return irb_.CreateLShr(src1_value, src2_value);
128275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
128375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  default:
128475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    LOG(FATAL) << "Unknown integer shift kind: " << kind;
128575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    return NULL;
128675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  }
128775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien}
128875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
12895a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYallvm::Value* GBCExpanderPass::Expand_HLArrayGet(llvm::CallInst& call_inst,
12905a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa                                                JType elem_jty) {
12915a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
12925a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* array_addr = call_inst.getArgOperand(1);
12935a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* index_value = call_inst.getArgOperand(2);
1294920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
12955a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
1296920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1297920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    EmitGuard_NullPointerException(dex_pc, array_addr);
1298920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  }
1299920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) {
1300920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value);
1301920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  }
13025a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13035a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
13045a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13055a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
13065a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13075a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  switch (elem_jty) {
13085a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kVoid:
13095a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    break;
13105a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13115a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kBoolean:
13125a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kChar:
13135a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    array_elem_value = irb_.CreateZExt(array_elem_value, irb_.getJType(elem_jty, kReg));
13145a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    break;
13155a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13165a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kByte:
13175a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kShort:
13185a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    array_elem_value = irb_.CreateSExt(array_elem_value, irb_.getJType(elem_jty, kReg));
13195a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    break;
13205a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13215a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kInt:
13225a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kLong:
13235a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kFloat:
13245a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kDouble:
13255a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kObject:
13265a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    break;
13275a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13285a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  default:
13295a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    LOG(FATAL) << "Unknown java type: " << elem_jty;
13305a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  }
13315a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13325a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  return array_elem_value;
13335a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa}
13345a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13355a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13365a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYavoid GBCExpanderPass::Expand_HLArrayPut(llvm::CallInst& call_inst,
13375a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa                                        JType elem_jty) {
13385a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
13395a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* new_value = call_inst.getArgOperand(1);
13405a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* array_addr = call_inst.getArgOperand(2);
13415a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* index_value = call_inst.getArgOperand(3);
1342920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
13435a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
1344920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1345920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    EmitGuard_NullPointerException(dex_pc, array_addr);
1346920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  }
1347920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) {
1348920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value);
1349920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  }
13505a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13515a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  switch (elem_jty) {
13525a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kVoid:
13535a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    break;
13545a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13555a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kBoolean:
13565a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kChar:
1357bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  case kByte:
1358bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  case kShort:
13595a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    new_value = irb_.CreateTrunc(new_value, irb_.getJType(elem_jty, kArray));
13605a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    break;
13615a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13625a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kInt:
13635a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kLong:
13645a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kFloat:
13655a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kDouble:
13665a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  case kObject:
13675a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    break;
13685a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13695a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  default:
13705a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    LOG(FATAL) << "Unknown java type: " << elem_jty;
13715a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  }
13725a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13735a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
13745a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13755a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  if (elem_jty == kObject) { // If put an object, check the type, and mark GC card table.
13765a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::CheckPutArrayElement);
13775a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13785a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    irb_.CreateCall2(runtime_func, new_value, array_addr);
13795a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13805a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    EmitGuard_ExceptionLandingPad(dex_pc);
13815a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13825a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    EmitMarkGCCard(new_value, array_addr);
13835a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  }
13845a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13855a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
13865a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13875a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  return;
13885a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa}
13895a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
13905e869b6560f918837cc6be3a50234deb2be46385TDYallvm::Value* GBCExpanderPass::Expand_HLIGet(llvm::CallInst& call_inst,
13915e869b6560f918837cc6be3a50234deb2be46385TDYa                                            JType field_jty) {
13925e869b6560f918837cc6be3a50234deb2be46385TDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
13935e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::Value* object_addr = call_inst.getArgOperand(1);
13945e869b6560f918837cc6be3a50234deb2be46385TDYa  uint32_t field_idx = LV2UInt(call_inst.getArgOperand(2));
1395920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
13965e869b6560f918837cc6be3a50234deb2be46385TDYa
1397920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1398920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    EmitGuard_NullPointerException(dex_pc, object_addr);
1399920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  }
14005e869b6560f918837cc6be3a50234deb2be46385TDYa
14015e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::Value* field_value;
14025e869b6560f918837cc6be3a50234deb2be46385TDYa
14035e869b6560f918837cc6be3a50234deb2be46385TDYa  int field_offset;
14045e869b6560f918837cc6be3a50234deb2be46385TDYa  bool is_volatile;
14055e869b6560f918837cc6be3a50234deb2be46385TDYa  bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
14065e869b6560f918837cc6be3a50234deb2be46385TDYa    field_idx, oat_compilation_unit_, field_offset, is_volatile, false);
14075e869b6560f918837cc6be3a50234deb2be46385TDYa
14085e869b6560f918837cc6be3a50234deb2be46385TDYa  if (!is_fast_path) {
14095e869b6560f918837cc6be3a50234deb2be46385TDYa    llvm::Function* runtime_func;
14105e869b6560f918837cc6be3a50234deb2be46385TDYa
14115e869b6560f918837cc6be3a50234deb2be46385TDYa    if (field_jty == kObject) {
14125e869b6560f918837cc6be3a50234deb2be46385TDYa      runtime_func = irb_.GetRuntime(runtime_support::GetObjectInstance);
14135e869b6560f918837cc6be3a50234deb2be46385TDYa    } else if (field_jty == kLong || field_jty == kDouble) {
14145e869b6560f918837cc6be3a50234deb2be46385TDYa      runtime_func = irb_.GetRuntime(runtime_support::Get64Instance);
14155e869b6560f918837cc6be3a50234deb2be46385TDYa    } else {
14165e869b6560f918837cc6be3a50234deb2be46385TDYa      runtime_func = irb_.GetRuntime(runtime_support::Get32Instance);
14175e869b6560f918837cc6be3a50234deb2be46385TDYa    }
14185e869b6560f918837cc6be3a50234deb2be46385TDYa
14195e869b6560f918837cc6be3a50234deb2be46385TDYa    llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
14205e869b6560f918837cc6be3a50234deb2be46385TDYa
14215e869b6560f918837cc6be3a50234deb2be46385TDYa    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
14225e869b6560f918837cc6be3a50234deb2be46385TDYa
14235e869b6560f918837cc6be3a50234deb2be46385TDYa    EmitUpdateDexPC(dex_pc);
14245e869b6560f918837cc6be3a50234deb2be46385TDYa
14255e869b6560f918837cc6be3a50234deb2be46385TDYa    field_value = irb_.CreateCall3(runtime_func, field_idx_value,
14265e869b6560f918837cc6be3a50234deb2be46385TDYa                                   method_object_addr, object_addr);
14275e869b6560f918837cc6be3a50234deb2be46385TDYa
14285e869b6560f918837cc6be3a50234deb2be46385TDYa    EmitGuard_ExceptionLandingPad(dex_pc);
14295e869b6560f918837cc6be3a50234deb2be46385TDYa
14305e869b6560f918837cc6be3a50234deb2be46385TDYa  } else {
14315e869b6560f918837cc6be3a50234deb2be46385TDYa    DCHECK_GE(field_offset, 0);
14325e869b6560f918837cc6be3a50234deb2be46385TDYa
14335e869b6560f918837cc6be3a50234deb2be46385TDYa    llvm::PointerType* field_type =
14345e869b6560f918837cc6be3a50234deb2be46385TDYa      irb_.getJType(field_jty, kField)->getPointerTo();
14355e869b6560f918837cc6be3a50234deb2be46385TDYa
14365e869b6560f918837cc6be3a50234deb2be46385TDYa    llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
14375e869b6560f918837cc6be3a50234deb2be46385TDYa
14385e869b6560f918837cc6be3a50234deb2be46385TDYa    llvm::Value* field_addr =
14395e869b6560f918837cc6be3a50234deb2be46385TDYa      irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
14405e869b6560f918837cc6be3a50234deb2be46385TDYa
14415e869b6560f918837cc6be3a50234deb2be46385TDYa    // TODO: Check is_volatile.  We need to generate atomic load instruction
14425e869b6560f918837cc6be3a50234deb2be46385TDYa    // when is_volatile is true.
14435e869b6560f918837cc6be3a50234deb2be46385TDYa    field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
14445e869b6560f918837cc6be3a50234deb2be46385TDYa  }
14455e869b6560f918837cc6be3a50234deb2be46385TDYa
14465e869b6560f918837cc6be3a50234deb2be46385TDYa  if (field_jty == kFloat || field_jty == kDouble) {
14475a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    field_value = irb_.CreateBitCast(field_value, irb_.getJType(field_jty, kAccurate));
14485e869b6560f918837cc6be3a50234deb2be46385TDYa  }
14495e869b6560f918837cc6be3a50234deb2be46385TDYa
14505e869b6560f918837cc6be3a50234deb2be46385TDYa  return field_value;
14515e869b6560f918837cc6be3a50234deb2be46385TDYa}
14525e869b6560f918837cc6be3a50234deb2be46385TDYa
14535e869b6560f918837cc6be3a50234deb2be46385TDYavoid GBCExpanderPass::Expand_HLIPut(llvm::CallInst& call_inst,
14545e869b6560f918837cc6be3a50234deb2be46385TDYa                                    JType field_jty) {
14555e869b6560f918837cc6be3a50234deb2be46385TDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1456bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  llvm::Value* new_value = call_inst.getArgOperand(1);
1457bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  llvm::Value* object_addr = call_inst.getArgOperand(2);
14585e869b6560f918837cc6be3a50234deb2be46385TDYa  uint32_t field_idx = LV2UInt(call_inst.getArgOperand(3));
1459920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
14605e869b6560f918837cc6be3a50234deb2be46385TDYa
14615e869b6560f918837cc6be3a50234deb2be46385TDYa  if (field_jty == kFloat || field_jty == kDouble) {
14625a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty, kField));
14635e869b6560f918837cc6be3a50234deb2be46385TDYa  }
14645e869b6560f918837cc6be3a50234deb2be46385TDYa
1465920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1466920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    EmitGuard_NullPointerException(dex_pc, object_addr);
1467920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  }
14685e869b6560f918837cc6be3a50234deb2be46385TDYa
14695e869b6560f918837cc6be3a50234deb2be46385TDYa  int field_offset;
14705e869b6560f918837cc6be3a50234deb2be46385TDYa  bool is_volatile;
14715e869b6560f918837cc6be3a50234deb2be46385TDYa  bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
14725e869b6560f918837cc6be3a50234deb2be46385TDYa    field_idx, oat_compilation_unit_, field_offset, is_volatile, true);
14735e869b6560f918837cc6be3a50234deb2be46385TDYa
14745e869b6560f918837cc6be3a50234deb2be46385TDYa  if (!is_fast_path) {
14755e869b6560f918837cc6be3a50234deb2be46385TDYa    llvm::Function* runtime_func;
14765e869b6560f918837cc6be3a50234deb2be46385TDYa
14775e869b6560f918837cc6be3a50234deb2be46385TDYa    if (field_jty == kObject) {
14785e869b6560f918837cc6be3a50234deb2be46385TDYa      runtime_func = irb_.GetRuntime(runtime_support::SetObjectInstance);
14795e869b6560f918837cc6be3a50234deb2be46385TDYa    } else if (field_jty == kLong || field_jty == kDouble) {
14805e869b6560f918837cc6be3a50234deb2be46385TDYa      runtime_func = irb_.GetRuntime(runtime_support::Set64Instance);
14815e869b6560f918837cc6be3a50234deb2be46385TDYa    } else {
14825e869b6560f918837cc6be3a50234deb2be46385TDYa      runtime_func = irb_.GetRuntime(runtime_support::Set32Instance);
14835e869b6560f918837cc6be3a50234deb2be46385TDYa    }
14845e869b6560f918837cc6be3a50234deb2be46385TDYa
14855e869b6560f918837cc6be3a50234deb2be46385TDYa    llvm::Value* field_idx_value = irb_.getInt32(field_idx);
14865e869b6560f918837cc6be3a50234deb2be46385TDYa
14875e869b6560f918837cc6be3a50234deb2be46385TDYa    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
14885e869b6560f918837cc6be3a50234deb2be46385TDYa
14895e869b6560f918837cc6be3a50234deb2be46385TDYa    EmitUpdateDexPC(dex_pc);
14905e869b6560f918837cc6be3a50234deb2be46385TDYa
14915e869b6560f918837cc6be3a50234deb2be46385TDYa    irb_.CreateCall4(runtime_func, field_idx_value,
14925e869b6560f918837cc6be3a50234deb2be46385TDYa                     method_object_addr, object_addr, new_value);
14935e869b6560f918837cc6be3a50234deb2be46385TDYa
14945e869b6560f918837cc6be3a50234deb2be46385TDYa    EmitGuard_ExceptionLandingPad(dex_pc);
14955e869b6560f918837cc6be3a50234deb2be46385TDYa
14965e869b6560f918837cc6be3a50234deb2be46385TDYa  } else {
14975e869b6560f918837cc6be3a50234deb2be46385TDYa    DCHECK_GE(field_offset, 0);
14985e869b6560f918837cc6be3a50234deb2be46385TDYa
14995e869b6560f918837cc6be3a50234deb2be46385TDYa    llvm::PointerType* field_type =
15005e869b6560f918837cc6be3a50234deb2be46385TDYa      irb_.getJType(field_jty, kField)->getPointerTo();
15015e869b6560f918837cc6be3a50234deb2be46385TDYa
15025e869b6560f918837cc6be3a50234deb2be46385TDYa    llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
15035e869b6560f918837cc6be3a50234deb2be46385TDYa
15045e869b6560f918837cc6be3a50234deb2be46385TDYa    llvm::Value* field_addr =
15055e869b6560f918837cc6be3a50234deb2be46385TDYa      irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
15065e869b6560f918837cc6be3a50234deb2be46385TDYa
15075e869b6560f918837cc6be3a50234deb2be46385TDYa    // TODO: Check is_volatile.  We need to generate atomic store instruction
15085e869b6560f918837cc6be3a50234deb2be46385TDYa    // when is_volatile is true.
15095e869b6560f918837cc6be3a50234deb2be46385TDYa    irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
15105e869b6560f918837cc6be3a50234deb2be46385TDYa
15115e869b6560f918837cc6be3a50234deb2be46385TDYa    if (field_jty == kObject) { // If put an object, mark the GC card table.
15125e869b6560f918837cc6be3a50234deb2be46385TDYa      EmitMarkGCCard(new_value, object_addr);
15135e869b6560f918837cc6be3a50234deb2be46385TDYa    }
15145e869b6560f918837cc6be3a50234deb2be46385TDYa  }
15155e869b6560f918837cc6be3a50234deb2be46385TDYa
15165e869b6560f918837cc6be3a50234deb2be46385TDYa  return;
15175e869b6560f918837cc6be3a50234deb2be46385TDYa}
15185e869b6560f918837cc6be3a50234deb2be46385TDYa
1519f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYallvm::Value* GBCExpanderPass::EmitLoadConstantClass(uint32_t dex_pc,
1520f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                                    uint32_t type_idx) {
1521bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  if (!compiler_->CanAccessTypeWithoutChecks(method_idx_, *dex_file_, type_idx)) {
1522f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* type_idx_value = irb_.getInt32(type_idx);
1523f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1524f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1525f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1526f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1527f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1528f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Function* runtime_func =
1529f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      irb_.GetRuntime(runtime_support::InitializeTypeAndVerifyAccess);
1530f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1531f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    EmitUpdateDexPC(dex_pc);
1532f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1533f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* type_object_addr =
1534f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1535f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1536f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    EmitGuard_ExceptionLandingPad(dex_pc);
1537f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1538f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    return type_object_addr;
1539f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1540f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  } else {
1541f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // Try to load the class (type) object from the test cache.
1542f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* type_field_addr =
1543f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
1544f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1545ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa    llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
1546f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1547bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao    if (compiler_->CanAssumeTypeIsPresentInDexCache(*dex_file_, type_idx)) {
1548f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      return type_object_addr;
1549f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    }
1550f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1551f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1552f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1553f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // Test whether class (type) object is in the dex cache or not
1554f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* equal_null =
1555f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      irb_.CreateICmpEQ(type_object_addr, irb_.getJNull());
1556f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1557f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::BasicBlock* block_cont =
1558f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      CreateBasicBlockWithDexPC(dex_pc, "cont");
1559f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1560f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::BasicBlock* block_load_class =
1561f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      CreateBasicBlockWithDexPC(dex_pc, "load_class");
1562f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1563f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.CreateCondBr(equal_null, block_load_class, block_cont, kUnlikely);
1564f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1565f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // Failback routine to load the class object
1566f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.SetInsertPoint(block_load_class);
1567f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1568f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeType);
1569f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1570f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1571f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1572f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1573f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1574f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1575f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1576f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    EmitUpdateDexPC(dex_pc);
1577f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1578f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* loaded_type_object_addr =
1579f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1580f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1581f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    EmitGuard_ExceptionLandingPad(dex_pc);
1582f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1583f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
1584f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1585f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.CreateBr(block_cont);
1586f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1587f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // Now the class object must be loaded
1588f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.SetInsertPoint(block_cont);
1589f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1590f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1591f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1592f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    phi->addIncoming(type_object_addr, block_original);
1593f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    phi->addIncoming(loaded_type_object_addr, block_after_load_class);
1594f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1595f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    return phi;
1596f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  }
1597f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa}
1598f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
15995a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYallvm::Value* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc,
16005a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa                                                    uint32_t type_idx) {
16015a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::BasicBlock* block_load_static =
16025a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    CreateBasicBlockWithDexPC(dex_pc, "load_static");
16035a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16045a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
16055a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16065a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  // Load static storage from dex cache
16075a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* storage_field_addr =
16085a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
16095a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
1610ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
16115a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16125a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::BasicBlock* block_original = irb_.GetInsertBlock();
16135a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16145a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  // Test: Is the static storage of this class initialized?
16155a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* equal_null =
16165a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
16175a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16185a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely);
16195a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16205a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  // Failback routine to load the class object
16215a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  irb_.SetInsertPoint(block_load_static);
16225a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16235a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeStaticStorage);
16245a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16255a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
16265a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16275a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
16285a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16295a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
16305a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16315a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  EmitUpdateDexPC(dex_pc);
16325a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16335a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* loaded_storage_object_addr =
16345a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
16355a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16365a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  EmitGuard_ExceptionLandingPad(dex_pc);
16375a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16385a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
16395a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16405a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  irb_.CreateBr(block_cont);
16415a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16425a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  // Now the class object must be loaded
16435a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  irb_.SetInsertPoint(block_cont);
16445a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16455a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
16465a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16475a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  phi->addIncoming(storage_object_addr, block_original);
16485a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
16495a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16505a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  return phi;
16515a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa}
16525a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16535a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYallvm::Value* GBCExpanderPass::Expand_HLSget(llvm::CallInst& call_inst,
16545a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa                                            JType field_jty) {
16555a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
16565a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
16575a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16585a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  int field_offset;
16595a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  int ssb_index;
16605a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  bool is_referrers_class;
16615a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  bool is_volatile;
16625a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16635a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  bool is_fast_path = compiler_->ComputeStaticFieldInfo(
16645a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    field_idx, oat_compilation_unit_, field_offset, ssb_index,
16655a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    is_referrers_class, is_volatile, false);
16665a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16675a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* static_field_value;
16685a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16695a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  if (!is_fast_path) {
16705a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    llvm::Function* runtime_func;
16715a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16725a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    if (field_jty == kObject) {
16735a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      runtime_func = irb_.GetRuntime(runtime_support::GetObjectStatic);
16745a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    } else if (field_jty == kLong || field_jty == kDouble) {
16755a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      runtime_func = irb_.GetRuntime(runtime_support::Get64Static);
16765a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    } else {
16775a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      runtime_func = irb_.GetRuntime(runtime_support::Get32Static);
16785a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    }
16795a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16805a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
16815a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16825a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
16835a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16845a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    EmitUpdateDexPC(dex_pc);
16855a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16865a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    static_field_value =
16875a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
16885a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16895a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    EmitGuard_ExceptionLandingPad(dex_pc);
16905a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16915a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  } else {
16925a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    DCHECK_GE(field_offset, 0);
16935a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16945a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    llvm::Value* static_storage_addr = NULL;
16955a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
16965a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    if (is_referrers_class) {
16975a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      // Fast path, static storage base is this method's class
16985a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
16995a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17005a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      static_storage_addr =
17015a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa        irb_.LoadFromObjectOffset(method_object_addr,
170266f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier                                  art::AbstractMethod::DeclaringClassOffset().Int32Value(),
17035a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa                                  irb_.getJObjectTy(),
17045a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa                                  kTBAAConstJObject);
17055a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    } else {
17065a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      // Medium path, static storage base in a different class which
17075a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      // requires checks that the other class is initialized
17085a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      DCHECK_GE(ssb_index, 0);
17095a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
17105a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    }
17115a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17125a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
17135a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17145a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    llvm::Value* static_field_addr =
17155a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
17165a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa                         irb_.getJType(field_jty, kField)->getPointerTo());
17175a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17185a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    // TODO: Check is_volatile.  We need to generate atomic load instruction
17195a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    // when is_volatile is true.
17205a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    static_field_value = irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
17215a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  }
17225a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17235a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  if (field_jty == kFloat || field_jty == kDouble) {
17245a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    static_field_value =
17255a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa        irb_.CreateBitCast(static_field_value, irb_.getJType(field_jty, kAccurate));
17265a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  }
17275a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17285a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  return static_field_value;
17295a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa}
17305a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17315a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYavoid GBCExpanderPass::Expand_HLSput(llvm::CallInst& call_inst,
17325a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa                                    JType field_jty) {
17335a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
17345a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
17355a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  llvm::Value* new_value = call_inst.getArgOperand(1);
17365a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17375a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  if (field_jty == kFloat || field_jty == kDouble) {
17385a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty, kField));
17395a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  }
17405a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17415a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  int field_offset;
17425a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  int ssb_index;
17435a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  bool is_referrers_class;
17445a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  bool is_volatile;
17455a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17465a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  bool is_fast_path = compiler_->ComputeStaticFieldInfo(
17475a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    field_idx, oat_compilation_unit_, field_offset, ssb_index,
17485a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    is_referrers_class, is_volatile, true);
17495a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17505a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  if (!is_fast_path) {
17515a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    llvm::Function* runtime_func;
17525a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17535a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    if (field_jty == kObject) {
17545a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      runtime_func = irb_.GetRuntime(runtime_support::SetObjectStatic);
17555a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    } else if (field_jty == kLong || field_jty == kDouble) {
17565a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      runtime_func = irb_.GetRuntime(runtime_support::Set64Static);
17575a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    } else {
17585a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      runtime_func = irb_.GetRuntime(runtime_support::Set32Static);
17595a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    }
17605a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17615a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
17625a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17635a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
17645a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17655a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    EmitUpdateDexPC(dex_pc);
17665a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17675a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    irb_.CreateCall3(runtime_func, field_idx_value,
17685a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa                     method_object_addr, new_value);
17695a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17705a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    EmitGuard_ExceptionLandingPad(dex_pc);
17715a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17725a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  } else {
17735a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    DCHECK_GE(field_offset, 0);
17745a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17755a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    llvm::Value* static_storage_addr = NULL;
17765a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17775a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    if (is_referrers_class) {
17785a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      // Fast path, static storage base is this method's class
17795a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
17805a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17815a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      static_storage_addr =
17825a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa        irb_.LoadFromObjectOffset(method_object_addr,
178366f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier                                  art::AbstractMethod::DeclaringClassOffset().Int32Value(),
17845a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa                                  irb_.getJObjectTy(),
17855a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa                                  kTBAAConstJObject);
17865a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    } else {
17875a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      // Medium path, static storage base in a different class which
17885a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      // requires checks that the other class is initialized
17895a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      DCHECK_GE(ssb_index, 0);
17905a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
17915a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    }
17925a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17935a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
17945a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17955a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    llvm::Value* static_field_addr =
17965a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
17975a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa                         irb_.getJType(field_jty, kField)->getPointerTo());
17985a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
17995a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    // TODO: Check is_volatile.  We need to generate atomic store instruction
18005a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    // when is_volatile is true.
18015a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
18025a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
18035a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    if (field_jty == kObject) { // If put an object, mark the GC card table.
18045a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      EmitMarkGCCard(new_value, static_storage_addr);
18055a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa    }
18065a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  }
18075a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
18085a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa  return;
18095a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa}
18105a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa
1811f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYallvm::Value* GBCExpanderPass::Expand_ConstString(llvm::CallInst& call_inst) {
1812f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1813f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t string_idx = LV2UInt(call_inst.getArgOperand(0));
1814f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1815f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
1816f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1817ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
1818f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1819bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  if (!compiler_->CanAssumeStringIsPresentInDexCache(*dex_file_, string_idx)) {
1820f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::BasicBlock* block_str_exist =
1821f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      CreateBasicBlockWithDexPC(dex_pc, "str_exist");
1822f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1823f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::BasicBlock* block_str_resolve =
1824f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
1825f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1826f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::BasicBlock* block_cont =
1827f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      CreateBasicBlockWithDexPC(dex_pc, "str_cont");
1828f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1829f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // Test: Is the string resolved and in the dex cache?
1830f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.getJNull());
1831f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1832f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist, kUnlikely);
1833f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1834f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // String is resolved, go to next basic block.
1835f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.SetInsertPoint(block_str_exist);
1836f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.CreateBr(block_cont);
1837f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1838f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // String is not resolved yet, resolve it now.
1839f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.SetInsertPoint(block_str_resolve);
1840f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1841f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::ResolveString);
1842f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1843f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1844f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1845f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* string_idx_value = irb_.getInt32(string_idx);
1846f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1847f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    EmitUpdateDexPC(dex_pc);
1848f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1849f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* result = irb_.CreateCall2(runtime_func, method_object_addr,
1850f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                           string_idx_value);
1851f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1852f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    EmitGuard_ExceptionLandingPad(dex_pc);
1853f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1854bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao    irb_.CreateBr(block_cont);
1855bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao
1856bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao
1857f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::BasicBlock* block_pre_cont = irb_.GetInsertBlock();
1858f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1859f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.SetInsertPoint(block_cont);
1860f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1861f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1862f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1863f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    phi->addIncoming(string_addr, block_str_exist);
1864f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    phi->addIncoming(result, block_pre_cont);
1865f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1866f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    string_addr = phi;
1867f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  }
1868f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1869f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  return string_addr;
1870f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa}
1871f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1872f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYallvm::Value* GBCExpanderPass::Expand_ConstClass(llvm::CallInst& call_inst) {
1873f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1874f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1875f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1876f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
1877f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1878f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  return type_object_addr;
1879f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa}
1880f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1881f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYavoid GBCExpanderPass::Expand_MonitorEnter(llvm::CallInst& call_inst) {
1882f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1883f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* object_addr = call_inst.getArgOperand(1);
1884920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
1885f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1886920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1887920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    EmitGuard_NullPointerException(dex_pc, object_addr);
1888920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  }
1889f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1890ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa  EmitUpdateDexPC(dex_pc);
1891ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa
1892f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.Runtime().EmitLockObject(object_addr);
1893f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1894f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  return;
1895f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa}
1896f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1897f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYavoid GBCExpanderPass::Expand_MonitorExit(llvm::CallInst& call_inst) {
1898f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1899f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* object_addr = call_inst.getArgOperand(1);
1900920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
1901f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1902920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1903920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    EmitGuard_NullPointerException(dex_pc, object_addr);
1904920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  }
1905f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1906f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  EmitUpdateDexPC(dex_pc);
1907f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1908f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.Runtime().EmitUnlockObject(object_addr);
1909f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1910f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  EmitGuard_ExceptionLandingPad(dex_pc);
1911f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1912f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  return;
1913f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa}
1914f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1915f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYavoid GBCExpanderPass::Expand_HLCheckCast(llvm::CallInst& call_inst) {
1916f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1917f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1918f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* object_addr = call_inst.getArgOperand(1);
1919f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1920f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::BasicBlock* block_test_class =
1921f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    CreateBasicBlockWithDexPC(dex_pc, "test_class");
1922f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1923f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::BasicBlock* block_test_sub_class =
1924f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
1925f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1926f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::BasicBlock* block_cont =
1927f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    CreateBasicBlockWithDexPC(dex_pc, "checkcast_cont");
1928f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1929f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // Test: Is the reference equal to null?  Act as no-op when it is null.
1930f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
1931f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1932f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.CreateCondBr(equal_null,
1933f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                    block_cont,
1934f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                    block_test_class);
1935f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1936f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // Test: Is the object instantiated from the given class?
1937f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.SetInsertPoint(block_test_class);
1938f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
1939920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  DCHECK_EQ(art::Object::ClassOffset().Int32Value(), 0);
1940f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1941f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
1942f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1943f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* object_type_field_addr =
1944f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
1945f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1946f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* object_type_object_addr =
1947f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
1948f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1949f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* equal_class =
1950f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
1951f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1952f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.CreateCondBr(equal_class,
1953f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                    block_cont,
1954f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                    block_test_sub_class);
1955f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1956f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // Test: Is the object instantiated from the subclass of the given class?
1957f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.SetInsertPoint(block_test_sub_class);
1958f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1959f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  EmitUpdateDexPC(dex_pc);
1960f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1961f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.CreateCall2(irb_.GetRuntime(runtime_support::CheckCast),
1962f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                   type_object_addr, object_type_object_addr);
1963f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1964f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  EmitGuard_ExceptionLandingPad(dex_pc);
1965f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1966f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.CreateBr(block_cont);
1967f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1968f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.SetInsertPoint(block_cont);
1969f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1970f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  return;
1971f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa}
1972f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1973f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYallvm::Value* GBCExpanderPass::Expand_InstanceOf(llvm::CallInst& call_inst) {
1974f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1975f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1976f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* object_addr = call_inst.getArgOperand(1);
1977f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1978f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::BasicBlock* block_nullp =
1979f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      CreateBasicBlockWithDexPC(dex_pc, "nullp");
1980f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1981f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::BasicBlock* block_test_class =
1982f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      CreateBasicBlockWithDexPC(dex_pc, "test_class");
1983f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1984f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::BasicBlock* block_class_equals =
1985f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      CreateBasicBlockWithDexPC(dex_pc, "class_eq");
1986f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1987f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::BasicBlock* block_test_sub_class =
1988f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
1989f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1990f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::BasicBlock* block_cont =
1991f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      CreateBasicBlockWithDexPC(dex_pc, "instance_of_cont");
1992f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
1993f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // Overview of the following code :
1994f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // We check for null, if so, then false, otherwise check for class == . If so
1995f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // then true, otherwise do callout slowpath.
1996f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  //
1997f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // Test: Is the reference equal to null?  Set 0 when it is null.
1998f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
1999f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2000f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.CreateCondBr(equal_null, block_nullp, block_test_class);
2001f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2002f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.SetInsertPoint(block_nullp);
2003f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.CreateBr(block_cont);
2004f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2005f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // Test: Is the object instantiated from the given class?
2006f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.SetInsertPoint(block_test_class);
2007f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
2008920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  DCHECK_EQ(art::Object::ClassOffset().Int32Value(), 0);
2009f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2010f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
2011f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2012f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* object_type_field_addr =
2013f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
2014f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2015f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* object_type_object_addr =
2016f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
2017f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2018f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* equal_class =
2019f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
2020f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2021f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class);
2022f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2023f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.SetInsertPoint(block_class_equals);
2024f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.CreateBr(block_cont);
2025f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2026f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // Test: Is the object instantiated from the subclass of the given class?
2027f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.SetInsertPoint(block_test_sub_class);
2028f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* result =
2029f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.CreateCall2(irb_.GetRuntime(runtime_support::IsAssignable),
2030f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                     type_object_addr, object_type_object_addr);
2031f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.CreateBr(block_cont);
2032f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2033f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  irb_.SetInsertPoint(block_cont);
2034f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2035f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::PHINode* phi = irb_.CreatePHI(irb_.getJIntTy(), 3);
2036f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2037f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  phi->addIncoming(irb_.getJInt(0), block_nullp);
2038f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  phi->addIncoming(irb_.getJInt(1), block_class_equals);
2039f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  phi->addIncoming(result, block_test_sub_class);
2040f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2041f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  return phi;
2042f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa}
2043f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2044f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYallvm::Value* GBCExpanderPass::Expand_NewInstance(llvm::CallInst& call_inst) {
2045f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2046f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2047f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2048f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Function* runtime_func;
2049bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  if (compiler_->CanAccessInstantiableTypeWithoutChecks(method_idx_, *dex_file_, type_idx)) {
2050f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    runtime_func = irb_.GetRuntime(runtime_support::AllocObject);
2051f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  } else {
2052f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    runtime_func = irb_.GetRuntime(runtime_support::AllocObjectWithAccessCheck);
2053f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  }
2054f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2055f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2056f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2057f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2058f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2059f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2060f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2061f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  EmitUpdateDexPC(dex_pc);
2062f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2063f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* object_addr =
2064f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.CreateCall3(runtime_func, type_index_value, method_object_addr, thread_object_addr);
2065f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2066f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  EmitGuard_ExceptionLandingPad(dex_pc);
2067f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2068f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  return object_addr;
2069f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa}
2070f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2071f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYallvm::Value* GBCExpanderPass::Expand_HLInvoke(llvm::CallInst& call_inst) {
2072f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2073920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  art::InvokeType invoke_type = static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
2074920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  bool is_static = (invoke_type == art::kStatic);
2075f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t callee_method_idx = LV2UInt(call_inst.getArgOperand(1));
2076920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  int opt_flags = LV2UInt(call_inst.getArgOperand(2));
2077f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2078f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // Compute invoke related information for compiler decision
2079f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  int vtable_idx = -1;
2080f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uintptr_t direct_code = 0;
2081f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uintptr_t direct_method = 0;
2082f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  bool is_fast_path = compiler_->
2083f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    ComputeInvokeInfo(callee_method_idx, oat_compilation_unit_,
2084f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                      invoke_type, vtable_idx, direct_code, direct_method);
2085f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2086f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // Load *this* actual parameter
2087f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* this_addr = NULL;
2088f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2089f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  if (!is_static) {
2090f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // Test: Is *this* parameter equal to null?
2091f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    this_addr = call_inst.getArgOperand(3);
2092f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  }
2093f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2094f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // Load the method object
2095f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* callee_method_object_addr = NULL;
2096f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2097f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  if (!is_fast_path) {
2098f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    callee_method_object_addr =
2099f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx, invoke_type,
2100f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                               this_addr, dex_pc, is_fast_path);
2101f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2102920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    if (!is_static && !(opt_flags & MIR_IGNORE_NULL_CHECK)) {
2103f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      EmitGuard_NullPointerException(dex_pc, this_addr);
2104f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    }
2105f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  } else {
2106920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    if (!is_static && !(opt_flags & MIR_IGNORE_NULL_CHECK)) {
2107f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      EmitGuard_NullPointerException(dex_pc, this_addr);
2108f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    }
2109f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2110f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    switch (invoke_type) {
2111920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case art::kStatic:
2112920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case art::kDirect:
2113f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      if (direct_method != 0u &&
2114f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa          direct_method != static_cast<uintptr_t>(-1)) {
2115f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa        callee_method_object_addr =
2116f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa          irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_method),
2117f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                              irb_.getJObjectTy());
2118f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      } else {
2119f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa        callee_method_object_addr =
2120f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa          EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
2121f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      }
2122f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      break;
2123f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2124920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case art::kVirtual:
2125f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      DCHECK(vtable_idx != -1);
2126f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      callee_method_object_addr =
2127f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa        EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
2128f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      break;
2129f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2130920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case art::kSuper:
2131f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      LOG(FATAL) << "invoke-super should be promoted to invoke-direct in "
2132f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                    "the fast path.";
2133f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      break;
2134f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2135920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case art::kInterface:
2136f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      callee_method_object_addr =
2137f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa        EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx,
2138f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                                 invoke_type, this_addr,
2139f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                                 dex_pc, is_fast_path);
2140f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      break;
2141f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    }
2142f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  }
2143f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2144f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // Load the actual parameter
2145f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  std::vector<llvm::Value*> args;
2146f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2147f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  args.push_back(callee_method_object_addr); // method object for callee
2148f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2149f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  for (uint32_t i = 3; i < call_inst.getNumArgOperands(); ++i) {
2150f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    args.push_back(call_inst.getArgOperand(i));
2151f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  }
2152f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2153f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* code_addr;
2154f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  if (direct_code != 0u &&
2155f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      direct_code != static_cast<uintptr_t>(-1)) {
2156f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    code_addr =
2157f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_code),
2158f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                          GetFunctionType(callee_method_idx, is_static)->getPointerTo());
2159f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  } else {
2160f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    code_addr =
2161f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      irb_.LoadFromObjectOffset(callee_method_object_addr,
216266f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier                                art::AbstractMethod::GetCodeOffset().Int32Value(),
2163f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                GetFunctionType(callee_method_idx, is_static)->getPointerTo(),
2164ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa                                kTBAARuntimeInfo);
2165f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  }
2166f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2167f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // Invoke callee
2168f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  EmitUpdateDexPC(dex_pc);
2169f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* retval = irb_.CreateCall(code_addr, args);
2170f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  EmitGuard_ExceptionLandingPad(dex_pc);
2171f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2172f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  return retval;
2173f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa}
2174f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2175f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYallvm::Value* GBCExpanderPass::Expand_OptArrayLength(llvm::CallInst& call_inst) {
2176f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2177f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // Get the array object address
2178f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* array_addr = call_inst.getArgOperand(1);
2179920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  int opt_flags = LV2UInt(call_inst.getArgOperand(0));
2180f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2181920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
2182920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    EmitGuard_NullPointerException(dex_pc, array_addr);
2183920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  }
2184f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2185f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  // Get the array length and store it to the register
2186f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  return EmitLoadArrayLength(array_addr);
2187f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa}
2188f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2189f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYallvm::Value* GBCExpanderPass::Expand_NewArray(llvm::CallInst& call_inst) {
2190f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2191f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2192f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* length = call_inst.getArgOperand(1);
2193f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2194f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  return EmitAllocNewArray(dex_pc, length, type_idx, false);
2195f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa}
2196f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2197f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYallvm::Value* GBCExpanderPass::Expand_HLFilledNewArray(llvm::CallInst& call_inst) {
2198f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2199f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t type_idx = LV2UInt(call_inst.getArgOperand(1));
2200f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t length = call_inst.getNumArgOperands() - 3;
2201f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2202f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* object_addr =
2203f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    EmitAllocNewArray(dex_pc, irb_.getInt32(length), type_idx, true);
2204f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2205f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  if (length > 0) {
2206f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // Check for the element type
2207f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    uint32_t type_desc_len = 0;
2208f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    const char* type_desc =
2209f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      dex_file_->StringByTypeIdx(type_idx, &type_desc_len);
2210f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2211f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    DCHECK_GE(type_desc_len, 2u); // should be guaranteed by verifier
2212f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    DCHECK_EQ(type_desc[0], '['); // should be guaranteed by verifier
2213f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    bool is_elem_int_ty = (type_desc[1] == 'I');
2214f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2215f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    uint32_t alignment;
2216f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Constant* elem_size;
2217f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::PointerType* field_type;
2218f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2219f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
2220f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // as the element, thus we are only checking 2 cases: primitive int and
2221f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // non-primitive type.
2222f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    if (is_elem_int_ty) {
2223f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      alignment = sizeof(int32_t);
2224f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
2225f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      field_type = irb_.getJIntTy()->getPointerTo();
2226f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    } else {
2227f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      alignment = irb_.getSizeOfPtrEquivInt();
2228f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      elem_size = irb_.getSizeOfPtrEquivIntValue();
2229f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      field_type = irb_.getJObjectTy()->getPointerTo();
2230f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    }
2231f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2232f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* data_field_offset =
2233920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa      irb_.getPtrEquivInt(art::Array::DataOffset(alignment).Int32Value());
2234f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2235f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* data_field_addr =
2236f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      irb_.CreatePtrDisp(object_addr, data_field_offset, field_type);
2237f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2238f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // TODO: Tune this code.  Currently we are generating one instruction for
2239f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // one element which may be very space consuming.  Maybe changing to use
2240f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // memcpy may help; however, since we can't guarantee that the alloca of
2241f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // dalvik register are continuous, we can't perform such optimization yet.
2242f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    for (uint32_t i = 0; i < length; ++i) {
2243f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      llvm::Value* reg_value = call_inst.getArgOperand(i+3);
2244f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2245f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
2246f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2247f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      data_field_addr =
2248f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa        irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
2249f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    }
2250f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  }
2251f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2252f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  return object_addr;
2253f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa}
2254f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2255f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYavoid GBCExpanderPass::Expand_HLFillArrayData(llvm::CallInst& call_inst) {
2256f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2257f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  int32_t payload_offset = static_cast<int32_t>(dex_pc) +
2258f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                           LV2SInt(call_inst.getArgOperand(0));
2259f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* array_addr = call_inst.getArgOperand(1);
2260f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2261920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  const art::Instruction::ArrayDataPayload* payload =
2262920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    reinterpret_cast<const art::Instruction::ArrayDataPayload*>(
2263f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa        code_item_->insns_ + payload_offset);
2264f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2265f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  if (payload->element_count == 0) {
2266f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // When the number of the elements in the payload is zero, we don't have
2267f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // to copy any numbers.  However, we should check whether the array object
2268f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // address is equal to null or not.
2269f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    EmitGuard_NullPointerException(dex_pc, array_addr);
2270f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  } else {
2271f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // To save the code size, we are going to call the runtime function to
2272f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // copy the content from DexFile.
2273f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2274f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    // NOTE: We will check for the NullPointerException in the runtime.
2275f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2276f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::FillArrayData);
2277f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2278f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2279f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2280f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    EmitUpdateDexPC(dex_pc);
2281f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2282f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.CreateCall4(runtime_func,
2283f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                     method_object_addr, irb_.getInt32(dex_pc),
2284f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                     array_addr, irb_.getInt32(payload_offset));
2285f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2286f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    EmitGuard_ExceptionLandingPad(dex_pc);
2287f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  }
2288f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2289f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  return;
2290f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa}
2291f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2292f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYallvm::Value* GBCExpanderPass::EmitAllocNewArray(uint32_t dex_pc,
2293f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                                llvm::Value* array_length_value,
2294f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                                uint32_t type_idx,
2295f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                                bool is_filled_new_array) {
2296f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Function* runtime_func;
2297f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2298f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  bool skip_access_check =
2299bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao    compiler_->CanAccessTypeWithoutChecks(method_idx_, *dex_file_, type_idx);
2300f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2301f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2302f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  if (is_filled_new_array) {
2303f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    runtime_func = skip_access_check ?
2304f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      irb_.GetRuntime(runtime_support::CheckAndAllocArray) :
2305f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      irb_.GetRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck);
2306f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  } else {
2307f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    runtime_func = skip_access_check ?
2308f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      irb_.GetRuntime(runtime_support::AllocArray) :
2309f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      irb_.GetRuntime(runtime_support::AllocArrayWithAccessCheck);
2310f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  }
2311f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2312f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2313f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2314f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2315f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2316f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2317f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2318f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  EmitUpdateDexPC(dex_pc);
2319f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2320f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* object_addr =
2321f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.CreateCall4(runtime_func, type_index_value, method_object_addr,
2322f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                     array_length_value, thread_object_addr);
2323f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2324f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  EmitGuard_ExceptionLandingPad(dex_pc);
2325f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2326f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  return object_addr;
2327f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa}
2328f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2329f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYallvm::Value* GBCExpanderPass::
2330f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYaEmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
2331920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa                                         art::InvokeType invoke_type,
2332f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                         llvm::Value* this_addr,
2333f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                         uint32_t dex_pc,
2334f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                                         bool is_fast_path) {
2335f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2336f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Function* runtime_func = NULL;
2337f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2338f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  switch (invoke_type) {
2339920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  case art::kStatic:
2340f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    runtime_func = irb_.GetRuntime(runtime_support::FindStaticMethodWithAccessCheck);
2341f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    break;
2342f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2343920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  case art::kDirect:
2344f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    runtime_func = irb_.GetRuntime(runtime_support::FindDirectMethodWithAccessCheck);
2345f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    break;
2346f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2347920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  case art::kVirtual:
2348f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    runtime_func = irb_.GetRuntime(runtime_support::FindVirtualMethodWithAccessCheck);
2349f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    break;
2350f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2351920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  case art::kSuper:
2352f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    runtime_func = irb_.GetRuntime(runtime_support::FindSuperMethodWithAccessCheck);
2353f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    break;
2354f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2355920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  case art::kInterface:
2356f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    if (is_fast_path) {
2357f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethod);
2358f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    } else {
2359f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethodWithAccessCheck);
2360f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    }
2361f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    break;
2362f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  }
2363f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2364f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
2365f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2366f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  if (this_addr == NULL) {
2367920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    DCHECK_EQ(invoke_type, art::kStatic);
2368f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    this_addr = irb_.getJNull();
2369f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  }
2370f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2371f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
2372f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2373f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2374f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2375f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  EmitUpdateDexPC(dex_pc);
2376f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2377f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  llvm::Value* callee_method_object_addr =
2378f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    irb_.CreateCall4(runtime_func,
2379f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                     callee_method_idx_value,
2380f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                     this_addr,
2381f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                     caller_method_object_addr,
2382f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                     thread_object_addr);
2383f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2384f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  EmitGuard_ExceptionLandingPad(dex_pc);
2385f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2386f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa  return callee_method_object_addr;
2387f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa}
2388f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
23895e869b6560f918837cc6be3a50234deb2be46385TDYavoid GBCExpanderPass::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
23905e869b6560f918837cc6be3a50234deb2be46385TDYa  // Using runtime support, let the target can override by InlineAssembly.
23915e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.Runtime().EmitMarkGCCard(value, target_addr);
23925e869b6560f918837cc6be3a50234deb2be46385TDYa}
23935e869b6560f918837cc6be3a50234deb2be46385TDYa
23945e869b6560f918837cc6be3a50234deb2be46385TDYavoid GBCExpanderPass::EmitUpdateDexPC(uint32_t dex_pc) {
2395c531cefbfb5394413122e9f57d211ba436cff012buzbee#if defined(ART_USE_PORTABLE_COMPILER)
2396bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  if (shadow_frame_ == NULL) {
2397bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao    return;
2398bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  }
2399bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao#endif
24005e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.StoreToObjectOffset(shadow_frame_,
2401920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa                           art::ShadowFrame::DexPCOffset(),
24025e869b6560f918837cc6be3a50234deb2be46385TDYa                           irb_.getInt32(dex_pc),
24035e869b6560f918837cc6be3a50234deb2be46385TDYa                           kTBAAShadowFrame);
24045e869b6560f918837cc6be3a50234deb2be46385TDYa}
24055e869b6560f918837cc6be3a50234deb2be46385TDYa
24065e869b6560f918837cc6be3a50234deb2be46385TDYavoid GBCExpanderPass::EmitGuard_DivZeroException(uint32_t dex_pc,
24075e869b6560f918837cc6be3a50234deb2be46385TDYa                                                 llvm::Value* denominator,
24085e869b6560f918837cc6be3a50234deb2be46385TDYa                                                 JType op_jty) {
24095e869b6560f918837cc6be3a50234deb2be46385TDYa  DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
24105e869b6560f918837cc6be3a50234deb2be46385TDYa
24115e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::Constant* zero = irb_.getJZero(op_jty);
24125e869b6560f918837cc6be3a50234deb2be46385TDYa
24135e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
24145e869b6560f918837cc6be3a50234deb2be46385TDYa
24155e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
24165e869b6560f918837cc6be3a50234deb2be46385TDYa
24175e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
24185e869b6560f918837cc6be3a50234deb2be46385TDYa
24195e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
24205e869b6560f918837cc6be3a50234deb2be46385TDYa
24215e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.SetInsertPoint(block_exception);
24225e869b6560f918837cc6be3a50234deb2be46385TDYa  EmitUpdateDexPC(dex_pc);
24235e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowDivZeroException));
24245e869b6560f918837cc6be3a50234deb2be46385TDYa  EmitBranchExceptionLandingPad(dex_pc);
24255e869b6560f918837cc6be3a50234deb2be46385TDYa
24265e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.SetInsertPoint(block_continue);
24275e869b6560f918837cc6be3a50234deb2be46385TDYa}
24285e869b6560f918837cc6be3a50234deb2be46385TDYa
24295e869b6560f918837cc6be3a50234deb2be46385TDYavoid GBCExpanderPass::EmitGuard_NullPointerException(uint32_t dex_pc,
24305e869b6560f918837cc6be3a50234deb2be46385TDYa                                                     llvm::Value* object) {
24315e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
24325e869b6560f918837cc6be3a50234deb2be46385TDYa
24335e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::BasicBlock* block_exception =
24345e869b6560f918837cc6be3a50234deb2be46385TDYa    CreateBasicBlockWithDexPC(dex_pc, "nullp");
24355e869b6560f918837cc6be3a50234deb2be46385TDYa
24365e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::BasicBlock* block_continue =
24375e869b6560f918837cc6be3a50234deb2be46385TDYa    CreateBasicBlockWithDexPC(dex_pc, "cont");
24385e869b6560f918837cc6be3a50234deb2be46385TDYa
24395e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
24405e869b6560f918837cc6be3a50234deb2be46385TDYa
24415e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.SetInsertPoint(block_exception);
24425e869b6560f918837cc6be3a50234deb2be46385TDYa  EmitUpdateDexPC(dex_pc);
24435e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowNullPointerException),
24445e869b6560f918837cc6be3a50234deb2be46385TDYa                  irb_.getInt32(dex_pc));
24455e869b6560f918837cc6be3a50234deb2be46385TDYa  EmitBranchExceptionLandingPad(dex_pc);
24465e869b6560f918837cc6be3a50234deb2be46385TDYa
24475e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.SetInsertPoint(block_continue);
24485e869b6560f918837cc6be3a50234deb2be46385TDYa}
24495e869b6560f918837cc6be3a50234deb2be46385TDYa
24505e869b6560f918837cc6be3a50234deb2be46385TDYavoid
24515e869b6560f918837cc6be3a50234deb2be46385TDYaGBCExpanderPass::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
24525e869b6560f918837cc6be3a50234deb2be46385TDYa                                                          llvm::Value* array,
24535e869b6560f918837cc6be3a50234deb2be46385TDYa                                                          llvm::Value* index) {
24545e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::Value* array_len = EmitLoadArrayLength(array);
24555e869b6560f918837cc6be3a50234deb2be46385TDYa
24565e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
24575e869b6560f918837cc6be3a50234deb2be46385TDYa
24585e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::BasicBlock* block_exception =
24595e869b6560f918837cc6be3a50234deb2be46385TDYa    CreateBasicBlockWithDexPC(dex_pc, "overflow");
24605e869b6560f918837cc6be3a50234deb2be46385TDYa
24615e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::BasicBlock* block_continue =
24625e869b6560f918837cc6be3a50234deb2be46385TDYa    CreateBasicBlockWithDexPC(dex_pc, "cont");
24635e869b6560f918837cc6be3a50234deb2be46385TDYa
24645e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
24655e869b6560f918837cc6be3a50234deb2be46385TDYa
24665e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.SetInsertPoint(block_exception);
24675e869b6560f918837cc6be3a50234deb2be46385TDYa
24685e869b6560f918837cc6be3a50234deb2be46385TDYa  EmitUpdateDexPC(dex_pc);
24695e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.CreateCall2(irb_.GetRuntime(runtime_support::ThrowIndexOutOfBounds), index, array_len);
24705e869b6560f918837cc6be3a50234deb2be46385TDYa  EmitBranchExceptionLandingPad(dex_pc);
24715e869b6560f918837cc6be3a50234deb2be46385TDYa
24725e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.SetInsertPoint(block_continue);
24735e869b6560f918837cc6be3a50234deb2be46385TDYa}
24745e869b6560f918837cc6be3a50234deb2be46385TDYa
24755e869b6560f918837cc6be3a50234deb2be46385TDYallvm::FunctionType* GBCExpanderPass::GetFunctionType(uint32_t method_idx,
24765e869b6560f918837cc6be3a50234deb2be46385TDYa                                                     bool is_static) {
24775e869b6560f918837cc6be3a50234deb2be46385TDYa  // Get method signature
2478920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  art::DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
24795e869b6560f918837cc6be3a50234deb2be46385TDYa
24805e869b6560f918837cc6be3a50234deb2be46385TDYa  uint32_t shorty_size;
24815e869b6560f918837cc6be3a50234deb2be46385TDYa  const char* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
24825e869b6560f918837cc6be3a50234deb2be46385TDYa  CHECK_GE(shorty_size, 1u);
24835e869b6560f918837cc6be3a50234deb2be46385TDYa
24845e869b6560f918837cc6be3a50234deb2be46385TDYa  // Get return type
2485bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao
2486bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  char ret_shorty = shorty[0];
2487c531cefbfb5394413122e9f57d211ba436cff012buzbee#if defined(ART_USE_PORTABLE_COMPILER)
248826f10eed520942d3db754c31941e457048475f61buzbee  ret_shorty = art::RemapShorty(ret_shorty);
2489bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao#endif
2490bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  llvm::Type* ret_type = irb_.getJType(ret_shorty, kAccurate);
24915e869b6560f918837cc6be3a50234deb2be46385TDYa
24925e869b6560f918837cc6be3a50234deb2be46385TDYa  // Get argument type
24935e869b6560f918837cc6be3a50234deb2be46385TDYa  std::vector<llvm::Type*> args_type;
24945e869b6560f918837cc6be3a50234deb2be46385TDYa
24955e869b6560f918837cc6be3a50234deb2be46385TDYa  args_type.push_back(irb_.getJObjectTy()); // method object pointer
24965e869b6560f918837cc6be3a50234deb2be46385TDYa
24975e869b6560f918837cc6be3a50234deb2be46385TDYa  if (!is_static) {
24985e869b6560f918837cc6be3a50234deb2be46385TDYa    args_type.push_back(irb_.getJType('L', kAccurate)); // "this" object pointer
24995e869b6560f918837cc6be3a50234deb2be46385TDYa  }
25005e869b6560f918837cc6be3a50234deb2be46385TDYa
25015e869b6560f918837cc6be3a50234deb2be46385TDYa  for (uint32_t i = 1; i < shorty_size; ++i) {
2502c531cefbfb5394413122e9f57d211ba436cff012buzbee#if defined(ART_USE_PORTABLE_COMPILER)
250326f10eed520942d3db754c31941e457048475f61buzbee    char shorty_type = art::RemapShorty(shorty[i]);
2504f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    args_type.push_back(irb_.getJType(shorty_type, kAccurate));
2505f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa#else
25065e869b6560f918837cc6be3a50234deb2be46385TDYa    args_type.push_back(irb_.getJType(shorty[i], kAccurate));
2507f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa#endif
25085e869b6560f918837cc6be3a50234deb2be46385TDYa  }
25095e869b6560f918837cc6be3a50234deb2be46385TDYa
25105e869b6560f918837cc6be3a50234deb2be46385TDYa  return llvm::FunctionType::get(ret_type, args_type, false);
25115e869b6560f918837cc6be3a50234deb2be46385TDYa}
25125e869b6560f918837cc6be3a50234deb2be46385TDYa
25135e869b6560f918837cc6be3a50234deb2be46385TDYa
25145e869b6560f918837cc6be3a50234deb2be46385TDYallvm::BasicBlock* GBCExpanderPass::
25155e869b6560f918837cc6be3a50234deb2be46385TDYaCreateBasicBlockWithDexPC(uint32_t dex_pc, const char* postfix) {
25165e869b6560f918837cc6be3a50234deb2be46385TDYa  std::string name;
25175e869b6560f918837cc6be3a50234deb2be46385TDYa
25185e869b6560f918837cc6be3a50234deb2be46385TDYa#if !defined(NDEBUG)
2519920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  art::StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
25205e869b6560f918837cc6be3a50234deb2be46385TDYa#endif
25215e869b6560f918837cc6be3a50234deb2be46385TDYa
25225e869b6560f918837cc6be3a50234deb2be46385TDYa  return llvm::BasicBlock::Create(context_, name, func_);
25235e869b6560f918837cc6be3a50234deb2be46385TDYa}
25245e869b6560f918837cc6be3a50234deb2be46385TDYa
25255e869b6560f918837cc6be3a50234deb2be46385TDYallvm::BasicBlock* GBCExpanderPass::GetBasicBlock(uint32_t dex_pc) {
25265e869b6560f918837cc6be3a50234deb2be46385TDYa  DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
2527bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  CHECK(basic_blocks_[dex_pc] != NULL);
25285e869b6560f918837cc6be3a50234deb2be46385TDYa  return basic_blocks_[dex_pc];
25295e869b6560f918837cc6be3a50234deb2be46385TDYa}
25305e869b6560f918837cc6be3a50234deb2be46385TDYa
25315e869b6560f918837cc6be3a50234deb2be46385TDYaint32_t GBCExpanderPass::GetTryItemOffset(uint32_t dex_pc) {
25325e869b6560f918837cc6be3a50234deb2be46385TDYa  int32_t min = 0;
25335e869b6560f918837cc6be3a50234deb2be46385TDYa  int32_t max = code_item_->tries_size_ - 1;
25345e869b6560f918837cc6be3a50234deb2be46385TDYa
25355e869b6560f918837cc6be3a50234deb2be46385TDYa  while (min <= max) {
25365e869b6560f918837cc6be3a50234deb2be46385TDYa    int32_t mid = min + (max - min) / 2;
25375e869b6560f918837cc6be3a50234deb2be46385TDYa
2538920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    const art::DexFile::TryItem* ti = art::DexFile::GetTryItems(*code_item_, mid);
25395e869b6560f918837cc6be3a50234deb2be46385TDYa    uint32_t start = ti->start_addr_;
25405e869b6560f918837cc6be3a50234deb2be46385TDYa    uint32_t end = start + ti->insn_count_;
25415e869b6560f918837cc6be3a50234deb2be46385TDYa
25425e869b6560f918837cc6be3a50234deb2be46385TDYa    if (dex_pc < start) {
25435e869b6560f918837cc6be3a50234deb2be46385TDYa      max = mid - 1;
25445e869b6560f918837cc6be3a50234deb2be46385TDYa    } else if (dex_pc >= end) {
25455e869b6560f918837cc6be3a50234deb2be46385TDYa      min = mid + 1;
25465e869b6560f918837cc6be3a50234deb2be46385TDYa    } else {
25475e869b6560f918837cc6be3a50234deb2be46385TDYa      return mid; // found
25485e869b6560f918837cc6be3a50234deb2be46385TDYa    }
25495e869b6560f918837cc6be3a50234deb2be46385TDYa  }
25505e869b6560f918837cc6be3a50234deb2be46385TDYa
25515e869b6560f918837cc6be3a50234deb2be46385TDYa  return -1; // not found
25525e869b6560f918837cc6be3a50234deb2be46385TDYa}
25535e869b6560f918837cc6be3a50234deb2be46385TDYa
25545e869b6560f918837cc6be3a50234deb2be46385TDYallvm::BasicBlock* GBCExpanderPass::GetLandingPadBasicBlock(uint32_t dex_pc) {
25555e869b6560f918837cc6be3a50234deb2be46385TDYa  // Find the try item for this address in this method
25565e869b6560f918837cc6be3a50234deb2be46385TDYa  int32_t ti_offset = GetTryItemOffset(dex_pc);
25575e869b6560f918837cc6be3a50234deb2be46385TDYa
25585e869b6560f918837cc6be3a50234deb2be46385TDYa  if (ti_offset == -1) {
25595e869b6560f918837cc6be3a50234deb2be46385TDYa    return NULL; // No landing pad is available for this address.
25605e869b6560f918837cc6be3a50234deb2be46385TDYa  }
25615e869b6560f918837cc6be3a50234deb2be46385TDYa
25625e869b6560f918837cc6be3a50234deb2be46385TDYa  // Check for the existing landing pad basic block
25635e869b6560f918837cc6be3a50234deb2be46385TDYa  DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
25645e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
25655e869b6560f918837cc6be3a50234deb2be46385TDYa
25665e869b6560f918837cc6be3a50234deb2be46385TDYa  if (block_lpad) {
25675e869b6560f918837cc6be3a50234deb2be46385TDYa    // We have generated landing pad for this try item already.  Return the
25685e869b6560f918837cc6be3a50234deb2be46385TDYa    // same basic block.
25695e869b6560f918837cc6be3a50234deb2be46385TDYa    return block_lpad;
25705e869b6560f918837cc6be3a50234deb2be46385TDYa  }
25715e869b6560f918837cc6be3a50234deb2be46385TDYa
25725e869b6560f918837cc6be3a50234deb2be46385TDYa  // Get try item from code item
2573920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  const art::DexFile::TryItem* ti = art::DexFile::GetTryItems(*code_item_, ti_offset);
25745e869b6560f918837cc6be3a50234deb2be46385TDYa
25755e869b6560f918837cc6be3a50234deb2be46385TDYa  std::string lpadname;
25765e869b6560f918837cc6be3a50234deb2be46385TDYa
25775e869b6560f918837cc6be3a50234deb2be46385TDYa#if !defined(NDEBUG)
2578920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  art::StringAppendF(&lpadname, "lpad%d_%04x_to_%04x", ti_offset, ti->start_addr_, ti->handler_off_);
25795e869b6560f918837cc6be3a50234deb2be46385TDYa#endif
25805e869b6560f918837cc6be3a50234deb2be46385TDYa
25815e869b6560f918837cc6be3a50234deb2be46385TDYa  // Create landing pad basic block
25825e869b6560f918837cc6be3a50234deb2be46385TDYa  block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
25835e869b6560f918837cc6be3a50234deb2be46385TDYa
25845e869b6560f918837cc6be3a50234deb2be46385TDYa  // Change IRBuilder insert point
25855e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
25865e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.SetInsertPoint(block_lpad);
25875e869b6560f918837cc6be3a50234deb2be46385TDYa
25885e869b6560f918837cc6be3a50234deb2be46385TDYa  // Find catch block with matching type
25895e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
25905e869b6560f918837cc6be3a50234deb2be46385TDYa
25915e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
25925e869b6560f918837cc6be3a50234deb2be46385TDYa
25935e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::Value* catch_handler_index_value =
25945e869b6560f918837cc6be3a50234deb2be46385TDYa    irb_.CreateCall2(irb_.GetRuntime(runtime_support::FindCatchBlock),
25955e869b6560f918837cc6be3a50234deb2be46385TDYa                     method_object_addr, ti_offset_value);
25965e869b6560f918837cc6be3a50234deb2be46385TDYa
25975e869b6560f918837cc6be3a50234deb2be46385TDYa  // Switch instruction (Go to unwind basic block by default)
25985e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::SwitchInst* sw =
25995e869b6560f918837cc6be3a50234deb2be46385TDYa    irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
26005e869b6560f918837cc6be3a50234deb2be46385TDYa
26015e869b6560f918837cc6be3a50234deb2be46385TDYa  // Cases with matched catch block
2602920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa  art::CatchHandlerIterator iter(*code_item_, ti->start_addr_);
26035e869b6560f918837cc6be3a50234deb2be46385TDYa
26045e869b6560f918837cc6be3a50234deb2be46385TDYa  for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
26055e869b6560f918837cc6be3a50234deb2be46385TDYa    sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
26065e869b6560f918837cc6be3a50234deb2be46385TDYa  }
26075e869b6560f918837cc6be3a50234deb2be46385TDYa
26085e869b6560f918837cc6be3a50234deb2be46385TDYa  // Restore the orignal insert point for IRBuilder
26095e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.restoreIP(irb_ip_original);
26105e869b6560f918837cc6be3a50234deb2be46385TDYa
26115e869b6560f918837cc6be3a50234deb2be46385TDYa  // Cache this landing pad
26125e869b6560f918837cc6be3a50234deb2be46385TDYa  DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
26135e869b6560f918837cc6be3a50234deb2be46385TDYa  basic_block_landing_pads_[ti_offset] = block_lpad;
26145e869b6560f918837cc6be3a50234deb2be46385TDYa
26155e869b6560f918837cc6be3a50234deb2be46385TDYa  return block_lpad;
26165e869b6560f918837cc6be3a50234deb2be46385TDYa}
26175e869b6560f918837cc6be3a50234deb2be46385TDYa
26185e869b6560f918837cc6be3a50234deb2be46385TDYallvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() {
26195e869b6560f918837cc6be3a50234deb2be46385TDYa  // Check the existing unwinding baisc block block
26205e869b6560f918837cc6be3a50234deb2be46385TDYa  if (basic_block_unwind_ != NULL) {
26215e869b6560f918837cc6be3a50234deb2be46385TDYa    return basic_block_unwind_;
26225e869b6560f918837cc6be3a50234deb2be46385TDYa  }
26235e869b6560f918837cc6be3a50234deb2be46385TDYa
26245e869b6560f918837cc6be3a50234deb2be46385TDYa  // Create new basic block for unwinding
26255e869b6560f918837cc6be3a50234deb2be46385TDYa  basic_block_unwind_ =
26265e869b6560f918837cc6be3a50234deb2be46385TDYa    llvm::BasicBlock::Create(context_, "exception_unwind", func_);
26275e869b6560f918837cc6be3a50234deb2be46385TDYa
26285e869b6560f918837cc6be3a50234deb2be46385TDYa  // Change IRBuilder insert point
26295e869b6560f918837cc6be3a50234deb2be46385TDYa  llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
26305e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.SetInsertPoint(basic_block_unwind_);
26315e869b6560f918837cc6be3a50234deb2be46385TDYa
26325e869b6560f918837cc6be3a50234deb2be46385TDYa  // Pop the shadow frame
26335e869b6560f918837cc6be3a50234deb2be46385TDYa  Expand_PopShadowFrame();
26345e869b6560f918837cc6be3a50234deb2be46385TDYa
26355e869b6560f918837cc6be3a50234deb2be46385TDYa  // Emit the code to return default value (zero) for the given return type.
26365e869b6560f918837cc6be3a50234deb2be46385TDYa  char ret_shorty = oat_compilation_unit_->GetShorty()[0];
2637c531cefbfb5394413122e9f57d211ba436cff012buzbee#if defined(ART_USE_PORTABLE_COMPILER)
263826f10eed520942d3db754c31941e457048475f61buzbee  ret_shorty = art::RemapShorty(ret_shorty);
2639bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao#endif
26405e869b6560f918837cc6be3a50234deb2be46385TDYa  if (ret_shorty == 'V') {
26415e869b6560f918837cc6be3a50234deb2be46385TDYa    irb_.CreateRetVoid();
26425e869b6560f918837cc6be3a50234deb2be46385TDYa  } else {
26435e869b6560f918837cc6be3a50234deb2be46385TDYa    irb_.CreateRet(irb_.getJZero(ret_shorty));
26445e869b6560f918837cc6be3a50234deb2be46385TDYa  }
26455e869b6560f918837cc6be3a50234deb2be46385TDYa
26465e869b6560f918837cc6be3a50234deb2be46385TDYa  // Restore the orignal insert point for IRBuilder
26475e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.restoreIP(irb_ip_original);
26485e869b6560f918837cc6be3a50234deb2be46385TDYa
26495e869b6560f918837cc6be3a50234deb2be46385TDYa  return basic_block_unwind_;
26505e869b6560f918837cc6be3a50234deb2be46385TDYa}
26515e869b6560f918837cc6be3a50234deb2be46385TDYa
26525e869b6560f918837cc6be3a50234deb2be46385TDYavoid GBCExpanderPass::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
26535e869b6560f918837cc6be3a50234deb2be46385TDYa  if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
265455e5e6c5702e3f1f68bd83ae741af769740d9a74TDYa    landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
2655aa55887fd30484a77e7775dfbcddbee883ce6380TDYa                                                            irb_.GetInsertBlock()));
26565e869b6560f918837cc6be3a50234deb2be46385TDYa    irb_.CreateBr(lpad);
26575e869b6560f918837cc6be3a50234deb2be46385TDYa  } else {
26585e869b6560f918837cc6be3a50234deb2be46385TDYa    irb_.CreateBr(GetUnwindBasicBlock());
26595e869b6560f918837cc6be3a50234deb2be46385TDYa  }
26605e869b6560f918837cc6be3a50234deb2be46385TDYa}
26615e869b6560f918837cc6be3a50234deb2be46385TDYa
26625e869b6560f918837cc6be3a50234deb2be46385TDYavoid GBCExpanderPass::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
26639a14265c911b2e63bec51a814b8b6fd157745b57Jeff Hao  llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
2664a1ae861c673ab5160a2a7afee2ada806cb61966bjeffhao
26659a14265c911b2e63bec51a814b8b6fd157745b57Jeff Hao  llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
26665e869b6560f918837cc6be3a50234deb2be46385TDYa
26675e869b6560f918837cc6be3a50234deb2be46385TDYa  if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
266855e5e6c5702e3f1f68bd83ae741af769740d9a74TDYa    landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
2669aa55887fd30484a77e7775dfbcddbee883ce6380TDYa                                                            irb_.GetInsertBlock()));
26709a14265c911b2e63bec51a814b8b6fd157745b57Jeff Hao    irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
26715e869b6560f918837cc6be3a50234deb2be46385TDYa  } else {
26729a14265c911b2e63bec51a814b8b6fd157745b57Jeff Hao    irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
26735e869b6560f918837cc6be3a50234deb2be46385TDYa  }
26745e869b6560f918837cc6be3a50234deb2be46385TDYa
26755e869b6560f918837cc6be3a50234deb2be46385TDYa  irb_.SetInsertPoint(block_cont);
26765e869b6560f918837cc6be3a50234deb2be46385TDYa}
26775e869b6560f918837cc6be3a50234deb2be46385TDYa
267821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::Value*
267921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei LiaoGBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
268021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                                 llvm::CallInst& call_inst) {
268121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  switch (intr_id) {
268221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    //==- Thread -----------------------------------------------------------==//
268321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::GetCurrentThread: {
2684b672d1e48b6e02bb69c7cd9bcfa7509c81514c07TDYa      return irb_.Runtime().EmitGetCurrentThread();
268521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
268675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::CheckSuspend: {
2687ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa      Expand_TestSuspend(call_inst);
2688890ea89879ba555a08433146058d516575646c59TDYa      return NULL;
2689890ea89879ba555a08433146058d516575646c59TDYa    }
2690890ea89879ba555a08433146058d516575646c59TDYa    case IntrinsicHelper::TestSuspend: {
2691d54a23d0bfe93e4b0d14d857ac9cc0d317a1c4bbLogan Chien      Expand_TestSuspend(call_inst);
269275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
269375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
269421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::MarkGCCard: {
26959a129457c233b653c7a8f65c963509267252b0a7TDYa      Expand_MarkGCCard(call_inst);
26969a129457c233b653c7a8f65c963509267252b0a7TDYa      return NULL;
269721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
269875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
269921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    //==- Exception --------------------------------------------------------==//
270021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ThrowException: {
270121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::ThrowException, call_inst);
270221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
2703f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    case IntrinsicHelper::HLThrowException: {
2704f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2705f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2706f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      EmitUpdateDexPC(dex_pc);
2707f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2708f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowException),
2709f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa                      call_inst.getArgOperand(0));
2710f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa
2711f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      EmitGuard_ExceptionLandingPad(dex_pc);
2712f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      return NULL;
2713f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    }
271421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::GetException: {
2715823433dbf4afec17169d5ca738031af5b374e140TDYa      return irb_.Runtime().EmitGetAndClearException();
271621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
271721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::IsExceptionPending: {
271821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return irb_.Runtime().EmitIsExceptionPending();
271921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
272021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::FindCatchBlock: {
272121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
272221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
272321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ThrowDivZeroException: {
272421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
272521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
272621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ThrowNullPointerException: {
272721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
272821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
272921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ThrowIndexOutOfBounds: {
273021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
273121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
273275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
273375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //==- Const String -----------------------------------------------------==//
273475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::ConstString: {
2735f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      return Expand_ConstString(call_inst);
273675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
273721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::LoadStringFromDexCache: {
273821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
273921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
274021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ResolveString: {
274121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::ResolveString, call_inst);
274221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
274375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
274475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //==- Const Class ------------------------------------------------------==//
274575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::ConstClass: {
2746f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      return Expand_ConstClass(call_inst);
274775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
274821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
274921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
275021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
275121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::LoadTypeFromDexCache: {
275221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
275321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
275421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InitializeType: {
275521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::InitializeType, call_inst);
275621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
275775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
275821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    //==- Lock -------------------------------------------------------------==//
275921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::LockObject: {
276021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_LockObject(call_inst.getArgOperand(0));
276121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
276221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
276321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::UnlockObject: {
276421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_UnlockObject(call_inst.getArgOperand(0));
276521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
276621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
276775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
276821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    //==- Cast -------------------------------------------------------------==//
276921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::CheckCast: {
277021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::CheckCast, call_inst);
277121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
277275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLCheckCast: {
2773f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      Expand_HLCheckCast(call_inst);
277475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
277575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
277621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::IsAssignable: {
277721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
277821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
277975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
278021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    //==- Alloc ------------------------------------------------------------==//
278121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::AllocObject: {
278221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::AllocObject, call_inst);
278321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
278421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::AllocObjectWithAccessCheck: {
278521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
278621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
278775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
278875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //==- Instance ---------------------------------------------------------==//
278975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::NewInstance: {
2790f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      return Expand_NewInstance(call_inst);
279175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
279275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::InstanceOf: {
2793f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      return Expand_InstanceOf(call_inst);
279475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
279575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
279621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    //==- Array ------------------------------------------------------------==//
279775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::NewArray: {
2798f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      return Expand_NewArray(call_inst);
279975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
280075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::OptArrayLength: {
2801f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      return Expand_OptArrayLength(call_inst);
280275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
280321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ArrayLength: {
280421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return EmitLoadArrayLength(call_inst.getArgOperand(0));
280521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
280621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::AllocArray: {
280721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::AllocArray, call_inst);
280821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
280921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::AllocArrayWithAccessCheck: {
281021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
281121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst);
281221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
281321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::CheckAndAllocArray: {
281421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
281521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
281621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
281721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
281821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst);
281921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
282021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ArrayGet: {
282121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_ArrayGet(call_inst.getArgOperand(0),
282221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
282321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kInt);
282421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
282521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ArrayGetWide: {
282621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_ArrayGet(call_inst.getArgOperand(0),
282721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
282821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kLong);
282921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
283021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ArrayGetObject: {
283121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_ArrayGet(call_inst.getArgOperand(0),
283221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
283321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kObject);
283421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
283521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ArrayGetBoolean: {
283621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_ArrayGet(call_inst.getArgOperand(0),
283721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
283821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kBoolean);
283921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
284021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ArrayGetByte: {
284121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_ArrayGet(call_inst.getArgOperand(0),
284221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
284321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kByte);
284421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
284521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ArrayGetChar: {
284621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_ArrayGet(call_inst.getArgOperand(0),
284721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
284821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kChar);
284921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
285021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ArrayGetShort: {
285121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_ArrayGet(call_inst.getArgOperand(0),
285221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
285321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kShort);
285421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
285521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ArrayPut: {
285621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_ArrayPut(call_inst.getArgOperand(0),
285721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
285821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
285921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kInt);
286021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
286121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
286221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ArrayPutWide: {
286321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_ArrayPut(call_inst.getArgOperand(0),
286421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
286521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
286621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kLong);
286721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
286821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
286921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ArrayPutObject: {
287021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_ArrayPut(call_inst.getArgOperand(0),
287121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
287221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
287321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kObject);
287421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
287521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
287621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ArrayPutBoolean: {
287721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_ArrayPut(call_inst.getArgOperand(0),
287821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
287921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
288021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kBoolean);
288121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
288221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
288321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ArrayPutByte: {
288421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_ArrayPut(call_inst.getArgOperand(0),
288521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
288621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
288721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kByte);
288821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
288921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
289021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ArrayPutChar: {
289121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_ArrayPut(call_inst.getArgOperand(0),
289221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
289321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
289421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kChar);
289521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
289621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
289721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::ArrayPutShort: {
289821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_ArrayPut(call_inst.getArgOperand(0),
289921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
290021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
290121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kShort);
290221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
290321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
290421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::CheckPutArrayElement: {
290521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
290621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
290721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::FilledNewArray: {
290821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_FilledNewArray(call_inst);
290921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
291021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
291121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::FillArrayData: {
291221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
291321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
291475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLFillArrayData: {
2915f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      Expand_HLFillArrayData(call_inst);
291675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
291775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
291875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLFilledNewArray: {
2919f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      return Expand_HLFilledNewArray(call_inst);
292075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
292175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
292221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    //==- Instance Field ---------------------------------------------------==//
292321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldGet:
292421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldGetBoolean:
292521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldGetByte:
292621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldGetChar:
292721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldGetShort: {
292821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
292921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
293021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldGetWide: {
293121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
293221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
293321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldGetObject: {
293421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
293521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
293621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldGetFast: {
293721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_IGetFast(call_inst.getArgOperand(0),
293821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
293921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(2),
294021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kInt);
294121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
294221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldGetWideFast: {
294321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_IGetFast(call_inst.getArgOperand(0),
294421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
294521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(2),
294621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kLong);
294721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
294821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldGetObjectFast: {
294921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_IGetFast(call_inst.getArgOperand(0),
295021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
295121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(2),
295221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kObject);
295321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
295421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldGetBooleanFast: {
295521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_IGetFast(call_inst.getArgOperand(0),
295621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
295721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(2),
295821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kBoolean);
295921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
296021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldGetByteFast: {
296121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_IGetFast(call_inst.getArgOperand(0),
296221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
296321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(2),
296421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kByte);
296521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
296621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldGetCharFast: {
296721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_IGetFast(call_inst.getArgOperand(0),
296821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
296921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(2),
297021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kChar);
297121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
297221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldGetShortFast: {
297321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_IGetFast(call_inst.getArgOperand(0),
297421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
297521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(2),
297621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kShort);
297721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
297821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldPut:
297921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldPutBoolean:
298021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldPutByte:
298121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldPutChar:
298221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldPutShort: {
298321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
298421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
298521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldPutWide: {
298621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
298721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
298821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldPutObject: {
298921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
299021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
299121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldPutFast: {
299221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_IPutFast(call_inst.getArgOperand(0),
299321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
299421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
299521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(3),
299621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kInt);
299721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
299821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
299921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldPutWideFast: {
300021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_IPutFast(call_inst.getArgOperand(0),
300121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
300221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
300321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(3),
300421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kLong);
300521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
300621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
300721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldPutObjectFast: {
300821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_IPutFast(call_inst.getArgOperand(0),
300921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
301021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
301121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(3),
301221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kObject);
301321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
301421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
301521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldPutBooleanFast: {
301621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_IPutFast(call_inst.getArgOperand(0),
301721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
301821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
301921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(3),
302021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kBoolean);
302121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
302221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
302321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldPutByteFast: {
302421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_IPutFast(call_inst.getArgOperand(0),
302521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
302621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
302721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(3),
302821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kByte);
302921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
303021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
303121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldPutCharFast: {
303221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_IPutFast(call_inst.getArgOperand(0),
303321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
303421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
303521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(3),
303621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kChar);
303721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
303821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
303921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InstanceFieldPutShortFast: {
304021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_IPutFast(call_inst.getArgOperand(0),
304121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
304221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
304321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(3),
304421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kShort);
304521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
304621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
304775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
304821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    //==- Static Field -----------------------------------------------------==//
304921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldGet:
305021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldGetBoolean:
305121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldGetByte:
305221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldGetChar:
305321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldGetShort: {
305421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::Get32Static, call_inst);
305521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
305621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldGetWide: {
305721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::Get64Static, call_inst);
305821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
305921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldGetObject: {
306021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
306121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
306221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldGetFast: {
306321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_SGetFast(call_inst.getArgOperand(0),
306421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
306521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(2),
306621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kInt);
306721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
306821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldGetWideFast: {
306921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_SGetFast(call_inst.getArgOperand(0),
307021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
307121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(2),
307221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kLong);
307321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
307421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldGetObjectFast: {
307521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_SGetFast(call_inst.getArgOperand(0),
307621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
307721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(2),
307821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kObject);
307921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
308021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldGetBooleanFast: {
308121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_SGetFast(call_inst.getArgOperand(0),
308221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
308321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(2),
308421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kBoolean);
308521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
308621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldGetByteFast: {
308721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_SGetFast(call_inst.getArgOperand(0),
308821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
308921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(2),
309021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kByte);
309121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
309221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldGetCharFast: {
309321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_SGetFast(call_inst.getArgOperand(0),
309421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
309521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(2),
309621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kChar);
309721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
309821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldGetShortFast: {
309921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_SGetFast(call_inst.getArgOperand(0),
310021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(1),
310121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             call_inst.getArgOperand(2),
310221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                             kShort);
310321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
310421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldPut:
310521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldPutBoolean:
310621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldPutByte:
310721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldPutChar:
310821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldPutShort: {
310921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::Set32Static, call_inst);
311021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
311121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldPutWide: {
311221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::Set64Static, call_inst);
311321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
311421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldPutObject: {
311521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
311621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
311721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldPutFast: {
311821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_SPutFast(call_inst.getArgOperand(0),
311921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
312021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
312121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(3),
312221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kInt);
312321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
312421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
312521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldPutWideFast: {
312621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_SPutFast(call_inst.getArgOperand(0),
312721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
312821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
312921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(3),
313021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kLong);
313121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
313221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
313321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldPutObjectFast: {
313421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_SPutFast(call_inst.getArgOperand(0),
313521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
313621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
313721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(3),
313821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kObject);
313921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
314021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
314121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldPutBooleanFast: {
314221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_SPutFast(call_inst.getArgOperand(0),
314321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
314421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
314521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(3),
314621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kBoolean);
314721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
314821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
314921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldPutByteFast: {
315021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_SPutFast(call_inst.getArgOperand(0),
315121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
315221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
315321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(3),
315421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kByte);
315521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
315621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
315721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldPutCharFast: {
315821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_SPutFast(call_inst.getArgOperand(0),
315921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
316021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
316121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(3),
316221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kChar);
316321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
316421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
316521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::StaticFieldPutShortFast: {
316621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_SPutFast(call_inst.getArgOperand(0),
316721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(1),
316821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(2),
316921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      call_inst.getArgOperand(3),
317021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                      kShort);
317121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
317221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
317321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::LoadDeclaringClassSSB: {
317421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
317521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
317621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::LoadClassSSBFromDexCache: {
317721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
317821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
317921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InitializeAndLoadClassSSB: {
318021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
318121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
318275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
318375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //==- High-level Array -------------------------------------------------==//
318475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayGet: {
31855a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLArrayGet(call_inst, kInt);
318675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
318775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayGetBoolean: {
31885a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLArrayGet(call_inst, kBoolean);
318975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
319075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayGetByte: {
31915a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLArrayGet(call_inst, kByte);
319275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
319375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayGetChar: {
31945a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLArrayGet(call_inst, kChar);
319575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
319675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayGetShort: {
31975a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLArrayGet(call_inst, kShort);
319875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
319975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayGetFloat: {
32005a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLArrayGet(call_inst, kFloat);
320175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
320275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayGetWide: {
32035a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLArrayGet(call_inst, kLong);
320475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
320575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayGetDouble: {
32065a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLArrayGet(call_inst, kDouble);
320775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
320875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayGetObject: {
32095a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLArrayGet(call_inst, kObject);
321075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
321175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayPut: {
32125a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLArrayPut(call_inst, kInt);
321375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
321475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
321575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayPutBoolean: {
32165a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLArrayPut(call_inst, kBoolean);
321775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
321875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
321975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayPutByte: {
32205a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLArrayPut(call_inst, kByte);
322175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
322275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
322375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayPutChar: {
32245a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLArrayPut(call_inst, kChar);
322575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
322675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
322775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayPutShort: {
32285a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLArrayPut(call_inst, kShort);
322975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
323075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
323175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayPutFloat: {
32325a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLArrayPut(call_inst, kFloat);
323375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
323475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
323575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayPutWide: {
32365a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLArrayPut(call_inst, kLong);
323775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
323875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
323975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayPutDouble: {
32405a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLArrayPut(call_inst, kDouble);
324175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
324275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
324375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLArrayPutObject: {
32445a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLArrayPut(call_inst, kObject);
324575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
324675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
324775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
324875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //==- High-level Instance ----------------------------------------------==//
324975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIGet: {
32505e869b6560f918837cc6be3a50234deb2be46385TDYa      return Expand_HLIGet(call_inst, kInt);
325175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
325275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIGetBoolean: {
32535e869b6560f918837cc6be3a50234deb2be46385TDYa      return Expand_HLIGet(call_inst, kBoolean);
325475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
325575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIGetByte: {
32565e869b6560f918837cc6be3a50234deb2be46385TDYa      return Expand_HLIGet(call_inst, kByte);
325775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
325875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIGetChar: {
32595e869b6560f918837cc6be3a50234deb2be46385TDYa      return Expand_HLIGet(call_inst, kChar);
326075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
326175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIGetShort: {
32625e869b6560f918837cc6be3a50234deb2be46385TDYa      return Expand_HLIGet(call_inst, kShort);
326375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
326475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIGetFloat: {
32655e869b6560f918837cc6be3a50234deb2be46385TDYa      return Expand_HLIGet(call_inst, kFloat);
326675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
326775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIGetWide: {
32685e869b6560f918837cc6be3a50234deb2be46385TDYa      return Expand_HLIGet(call_inst, kLong);
326975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
327075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIGetDouble: {
32715e869b6560f918837cc6be3a50234deb2be46385TDYa      return Expand_HLIGet(call_inst, kDouble);
327275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
327375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIGetObject: {
32745e869b6560f918837cc6be3a50234deb2be46385TDYa      return Expand_HLIGet(call_inst, kObject);
327575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
327675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIPut: {
32775e869b6560f918837cc6be3a50234deb2be46385TDYa      Expand_HLIPut(call_inst, kInt);
327875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
327975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
328075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIPutBoolean: {
32815e869b6560f918837cc6be3a50234deb2be46385TDYa      Expand_HLIPut(call_inst, kBoolean);
328275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
328375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
328475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIPutByte: {
32855e869b6560f918837cc6be3a50234deb2be46385TDYa      Expand_HLIPut(call_inst, kByte);
328675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
328775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
328875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIPutChar: {
32895e869b6560f918837cc6be3a50234deb2be46385TDYa      Expand_HLIPut(call_inst, kChar);
329075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
329175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
329275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIPutShort: {
32935e869b6560f918837cc6be3a50234deb2be46385TDYa      Expand_HLIPut(call_inst, kShort);
329475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
329575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
329675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIPutFloat: {
32975e869b6560f918837cc6be3a50234deb2be46385TDYa      Expand_HLIPut(call_inst, kFloat);
329875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
329975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
330075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIPutWide: {
33015e869b6560f918837cc6be3a50234deb2be46385TDYa      Expand_HLIPut(call_inst, kLong);
330275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
330375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
330475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIPutDouble: {
33055e869b6560f918837cc6be3a50234deb2be46385TDYa      Expand_HLIPut(call_inst, kDouble);
330675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
330775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
330875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLIPutObject: {
33095e869b6560f918837cc6be3a50234deb2be46385TDYa      Expand_HLIPut(call_inst, kObject);
331075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
331175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
331275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
331375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //==- High-level Invoke ------------------------------------------------==//
3314f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    case IntrinsicHelper::HLInvokeVoid:
3315f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    case IntrinsicHelper::HLInvokeObj:
3316f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    case IntrinsicHelper::HLInvokeInt:
3317f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    case IntrinsicHelper::HLInvokeFloat:
3318f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa    case IntrinsicHelper::HLInvokeLong:
331975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLInvokeDouble: {
3320f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      return Expand_HLInvoke(call_inst);
332175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
332275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
332321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    //==- Invoke -----------------------------------------------------------==//
332421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
332521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
332621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
332721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
332821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
332921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
333021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
333121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
333221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
333321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
333421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
333521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
333621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
333721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
333821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
333921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
334021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
334121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
334221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
334321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_GetVirtualCalleeMethodObjAddrFast(
334421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao                call_inst.getArgOperand(0), call_inst.getArgOperand(1));
334521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
334621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
334721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
334821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
334921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InvokeRetVoid:
335021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InvokeRetBoolean:
335121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InvokeRetByte:
335221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InvokeRetChar:
335321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InvokeRetShort:
335421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InvokeRetInt:
335521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InvokeRetLong:
335621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InvokeRetFloat:
335721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InvokeRetDouble:
335821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::InvokeRetObject: {
335921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return Expand_Invoke(call_inst);
336021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
336175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
336221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    //==- Math -------------------------------------------------------------==//
336321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::DivInt: {
33644ec8ccdaeee1c4af1a70e1ac0dd482e83df72f38TDYa      return Expand_DivRem(call_inst, /* is_div */true, kInt);
336521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
336621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::RemInt: {
33674ec8ccdaeee1c4af1a70e1ac0dd482e83df72f38TDYa      return Expand_DivRem(call_inst, /* is_div */false, kInt);
336821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
336921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::DivLong: {
33704ec8ccdaeee1c4af1a70e1ac0dd482e83df72f38TDYa      return Expand_DivRem(call_inst, /* is_div */true, kLong);
337121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
337221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::RemLong: {
33734ec8ccdaeee1c4af1a70e1ac0dd482e83df72f38TDYa      return Expand_DivRem(call_inst, /* is_div */false, kLong);
337421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
337521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::D2L: {
337621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::art_d2l, call_inst);
337721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
337821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::D2I: {
337921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::art_d2i, call_inst);
338021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
338121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::F2L: {
338221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::art_f2l, call_inst);
338321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
338421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::F2I: {
338521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return ExpandToRuntime(runtime_support::art_f2i, call_inst);
338621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
338775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
338875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //==- High-level Static ------------------------------------------------==//
338975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSget: {
33905a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLSget(call_inst, kInt);
339175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
339275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSgetBoolean: {
33935a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLSget(call_inst, kBoolean);
339475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
339575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSgetByte: {
33965a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLSget(call_inst, kByte);
339775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
339875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSgetChar: {
33995a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLSget(call_inst, kChar);
340075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
340175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSgetShort: {
34025a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLSget(call_inst, kShort);
340375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
340475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSgetFloat: {
34055a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLSget(call_inst, kFloat);
340675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
340775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSgetWide: {
34085a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLSget(call_inst, kLong);
340975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
341075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSgetDouble: {
34115a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLSget(call_inst, kDouble);
341275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
341375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSgetObject: {
34145a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      return Expand_HLSget(call_inst, kObject);
341575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
341675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSput: {
34175a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLSput(call_inst, kInt);
341875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
341975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
342075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSputBoolean: {
34215a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLSput(call_inst, kBoolean);
342275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
342375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
342475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSputByte: {
34255a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLSput(call_inst, kByte);
342675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
342775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
342875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSputChar: {
34295a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLSput(call_inst, kChar);
343075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
343175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
343275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSputShort: {
34335a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLSput(call_inst, kShort);
343475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
343575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
343675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSputFloat: {
34375a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLSput(call_inst, kFloat);
343875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
343975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
344075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSputWide: {
34415a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLSput(call_inst, kLong);
344275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
344375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
344475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSputDouble: {
34455a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLSput(call_inst, kDouble);
344675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
344775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
344875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::HLSputObject: {
34495a26d44dc8e6fe59a3619ee5951a54bc53d7c9f1TDYa      Expand_HLSput(call_inst, kObject);
345075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
345175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
345275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
345375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //==- High-level Monitor -----------------------------------------------==//
345475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::MonitorEnter: {
3455f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      Expand_MonitorEnter(call_inst);
345675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
345775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
345875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::MonitorExit: {
3459f71bf5ad4e1872e4dfc71de65641ed518e2b38daTDYa      Expand_MonitorExit(call_inst);
346075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
346175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
346275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
346321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    //==- Shadow Frame -----------------------------------------------------==//
346421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::AllocaShadowFrame: {
3465ce4cc0d1818e872c1c7f3c3519a82259afd5c288TDYa      Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
346621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
346721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
34688e950c117975d23f50ed7e32ca5db01a813c25d0TDYa    case IntrinsicHelper::SetVReg: {
34698e950c117975d23f50ed7e32ca5db01a813c25d0TDYa      Expand_SetVReg(call_inst.getArgOperand(0),
34708e950c117975d23f50ed7e32ca5db01a813c25d0TDYa                     call_inst.getArgOperand(1));
34718e950c117975d23f50ed7e32ca5db01a813c25d0TDYa      return NULL;
34728e950c117975d23f50ed7e32ca5db01a813c25d0TDYa    }
347321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::PopShadowFrame: {
347421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_PopShadowFrame();
347521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
347621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
347721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    case IntrinsicHelper::UpdateDexPC: {
347821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      Expand_UpdateDexPC(call_inst.getArgOperand(0));
347921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao      return NULL;
348021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
3481a1b2185820e6080864d18a35759cc046dc4ee578TDYa
348275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //==- Comparison -------------------------------------------------------==//
3483a1b2185820e6080864d18a35759cc046dc4ee578TDYa    case IntrinsicHelper::CmplFloat:
3484a1b2185820e6080864d18a35759cc046dc4ee578TDYa    case IntrinsicHelper::CmplDouble: {
348575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return Expand_FPCompare(call_inst.getArgOperand(0),
348675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                              call_inst.getArgOperand(1),
348775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                              false);
3488a1b2185820e6080864d18a35759cc046dc4ee578TDYa    }
3489a1b2185820e6080864d18a35759cc046dc4ee578TDYa    case IntrinsicHelper::CmpgFloat:
3490a1b2185820e6080864d18a35759cc046dc4ee578TDYa    case IntrinsicHelper::CmpgDouble: {
349175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return Expand_FPCompare(call_inst.getArgOperand(0),
349275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                              call_inst.getArgOperand(1),
349375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                              true);
3494a1b2185820e6080864d18a35759cc046dc4ee578TDYa    }
3495a1b2185820e6080864d18a35759cc046dc4ee578TDYa    case IntrinsicHelper::CmpLong: {
349675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return Expand_LongCompare(call_inst.getArgOperand(0),
349775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                call_inst.getArgOperand(1));
349875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
349975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
350075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //==- Const ------------------------------------------------------------==//
3501920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::ConstInt:
3502920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::ConstLong: {
3503d54a23d0bfe93e4b0d14d857ac9cc0d317a1c4bbLogan Chien      return call_inst.getArgOperand(0);
350475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
3505920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::ConstFloat: {
3506d54a23d0bfe93e4b0d14d857ac9cc0d317a1c4bbLogan Chien      return irb_.CreateBitCast(call_inst.getArgOperand(0),
3507d54a23d0bfe93e4b0d14d857ac9cc0d317a1c4bbLogan Chien                                irb_.getJFloatTy());
350875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
3509920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::ConstDouble: {
3510d54a23d0bfe93e4b0d14d857ac9cc0d317a1c4bbLogan Chien      return irb_.CreateBitCast(call_inst.getArgOperand(0),
3511d54a23d0bfe93e4b0d14d857ac9cc0d317a1c4bbLogan Chien                                irb_.getJDoubleTy());
3512d54a23d0bfe93e4b0d14d857ac9cc0d317a1c4bbLogan Chien    }
3513920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::ConstObj: {
3514bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao      CHECK(LV2UInt(call_inst.getArgOperand(0)) == 0);
3515bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao      return irb_.getJNull();
3516a1b2185820e6080864d18a35759cc046dc4ee578TDYa    }
351775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
351875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //==- Method Info ------------------------------------------------------==//
3519920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::MethodInfo: {
3520b259652a72293b4bd3c346bb0e40fb8a7f878fa2Shih-wei Liao      // Nothing to be done, because MethodInfo carries optional hints that are
3521b259652a72293b4bd3c346bb0e40fb8a7f878fa2Shih-wei Liao      // not needed by the portable path.
352275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return NULL;
352375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
352475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
352575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //==- Copy -------------------------------------------------------------==//
3526920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::CopyInt:
3527920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::CopyFloat:
3528920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::CopyLong:
3529920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::CopyDouble:
3530920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::CopyObj: {
3531d54a23d0bfe93e4b0d14d857ac9cc0d317a1c4bbLogan Chien      return call_inst.getArgOperand(0);
353275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
353375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
353475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //==- Shift ------------------------------------------------------------==//
3535920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::SHLLong: {
353675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return Expand_IntegerShift(call_inst.getArgOperand(0),
353775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                 call_inst.getArgOperand(1),
353875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                 kIntegerSHL, kLong);
3539a1b2185820e6080864d18a35759cc046dc4ee578TDYa    }
3540920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::SHRLong: {
354175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return Expand_IntegerShift(call_inst.getArgOperand(0),
354275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                 call_inst.getArgOperand(1),
354375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                 kIntegerSHR, kLong);
3544a1b2185820e6080864d18a35759cc046dc4ee578TDYa    }
3545920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::USHRLong: {
354675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return Expand_IntegerShift(call_inst.getArgOperand(0),
354775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                 call_inst.getArgOperand(1),
354875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                 kIntegerUSHR, kLong);
3549a1b2185820e6080864d18a35759cc046dc4ee578TDYa    }
3550920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::SHLInt: {
355175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return Expand_IntegerShift(call_inst.getArgOperand(0),
355275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                 call_inst.getArgOperand(1),
355375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                 kIntegerSHL, kInt);
3554a1b2185820e6080864d18a35759cc046dc4ee578TDYa    }
3555920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::SHRInt: {
355675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return Expand_IntegerShift(call_inst.getArgOperand(0),
355775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                 call_inst.getArgOperand(1),
355875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                 kIntegerSHR, kInt);
3559a1b2185820e6080864d18a35759cc046dc4ee578TDYa    }
3560920be7cac2aa06f9d5c8b2db87db116b1cad3159TDYa    case IntrinsicHelper::USHRInt: {
356175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return Expand_IntegerShift(call_inst.getArgOperand(0),
356275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                 call_inst.getArgOperand(1),
356375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                                 kIntegerUSHR, kInt);
3564a1b2185820e6080864d18a35759cc046dc4ee578TDYa    }
356521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
356675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //==- Conversion -------------------------------------------------------==//
356775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::IntToChar: {
356875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
356975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                             irb_.getJIntTy());
357075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
357175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::IntToShort: {
357275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
357375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                             irb_.getJIntTy());
357421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao    }
357575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::IntToByte: {
357675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
357775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien                             irb_.getJIntTy());
357875e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    }
357975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien
358087caa7e1eb7a9ed56285062ef2feb650d42e3bb6TDYa    //==- Exception --------------------------------------------------------==//
358187caa7e1eb7a9ed56285062ef2feb650d42e3bb6TDYa    case IntrinsicHelper::CatchTargets: {
358255e5e6c5702e3f1f68bd83ae741af769740d9a74TDYa      UpdatePhiInstruction(current_bb_, irb_.GetInsertBlock());
358387caa7e1eb7a9ed56285062ef2feb650d42e3bb6TDYa      llvm::SwitchInst* si = llvm::dyn_cast<llvm::SwitchInst>(call_inst.getNextNode());
358487caa7e1eb7a9ed56285062ef2feb650d42e3bb6TDYa      CHECK(si != NULL);
358587caa7e1eb7a9ed56285062ef2feb650d42e3bb6TDYa      irb_.CreateBr(si->getDefaultDest());
358687caa7e1eb7a9ed56285062ef2feb650d42e3bb6TDYa      si->eraseFromParent();
358787caa7e1eb7a9ed56285062ef2feb650d42e3bb6TDYa      return call_inst.getArgOperand(0);
358887caa7e1eb7a9ed56285062ef2feb650d42e3bb6TDYa    }
358987caa7e1eb7a9ed56285062ef2feb650d42e3bb6TDYa
359075e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //==- Unknown Cases ----------------------------------------------------==//
359175e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::MaxIntrinsicId:
359275e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    case IntrinsicHelper::UnknownId:
359375e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien    //default:
359475e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      // NOTE: "default" is intentionally commented so that C/C++ compiler will
359575e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      // give some warning on unmatched cases.
359675e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      // NOTE: We should not implement these cases.
359775e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien      break;
359821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  }
359975e4b60d28355d4c33d50093d9d2603ffdea82dcLogan Chien  UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
360021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return NULL;
360121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
360221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
360321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao} // anonymous namespace
360421d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
360521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaonamespace art {
3606b259652a72293b4bd3c346bb0e40fb8a7f878fa2Shih-wei Liao
360721d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaonamespace compiler_llvm {
360821d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
360921d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liaollvm::FunctionPass*
361021d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei LiaoCreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb) {
361121d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao  return new GBCExpanderPass(intrinsic_helper, irb);
361221d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao}
361321d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao
3614bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liaollvm::FunctionPass*
3615bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei LiaoCreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
3616bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao                      Compiler* compiler, OatCompilationUnit* oat_compilation_unit) {
3617bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  if (compiler != NULL) {
3618bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao    return new GBCExpanderPass(intrinsic_helper, irb,
3619bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao                               compiler, oat_compilation_unit);
3620bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  } else {
3621bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao    return new GBCExpanderPass(intrinsic_helper, irb);
3622bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao  }
3623bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao}
3624bb33f2fa8e462937574a8cd1b744b86c2f762571Shih-wei Liao
362521d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao} // namespace compiler_llvm
362621d28f510eb590f52810c83f1f3f37fe5f4adf46Shih-wei Liao} // namespace art
3627