blob: 4c9b31cee6d113d47e32676dc8df3b69048ef779 [file] [log] [blame]
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "ir_builder.h"
18#include "utils_llvm.h"
19
TDYa1275e869b62012-07-25 00:45:39 -070020#include "compiler.h"
Ian Rogers76ae4fe2013-02-27 16:03:41 -080021#include "intrinsic_helper.h"
Ian Rogers98573f92013-01-30 17:26:32 -080022#include "mirror/abstract_method.h"
23#include "mirror/array.h"
TDYa1275e869b62012-07-25 00:45:39 -070024#include "oat_compilation_unit.h"
Shih-wei Liao21d28f52012-06-12 05:55:00 -070025#include "thread.h"
TDYa1275e869b62012-07-25 00:45:39 -070026#include "verifier/method_verifier.h"
Shih-wei Liao21d28f52012-06-12 05:55:00 -070027
buzbee395116c2013-02-27 14:30:25 -080028#include "compiler/dex/compiler_ir.h"
29#include "compiler/dex/quick/codegen.h"
TDYa127920be7c2012-09-10 17:13:22 -070030using art::kMIRIgnoreNullCheck;
31using art::kMIRIgnoreRangeCheck;
32
Shih-wei Liao21d28f52012-06-12 05:55:00 -070033#include <llvm/ADT/STLExtras.h>
34#include <llvm/Intrinsics.h>
Logan Chiend36a2ac2012-08-04 00:37:30 +080035#include <llvm/Metadata.h>
Shih-wei Liao21d28f52012-06-12 05:55:00 -070036#include <llvm/Pass.h>
37#include <llvm/Support/CFG.h>
38#include <llvm/Support/InstIterator.h>
39
40#include <vector>
TDYa127aa558872012-08-16 05:11:07 -070041#include <map>
42#include <utility>
Shih-wei Liao21d28f52012-06-12 05:55:00 -070043
TDYa127920be7c2012-09-10 17:13:22 -070044using namespace art::compiler_llvm;
Shih-wei Liao21d28f52012-06-12 05:55:00 -070045
Ian Rogers76ae4fe2013-02-27 16:03:41 -080046using art::compiler_llvm::IntrinsicHelper;
Shih-wei Liao21d28f52012-06-12 05:55:00 -070047
Shih-wei Liaob2596522012-09-14 16:36:11 -070048namespace art {
buzbee26f10ee2012-12-21 11:16:29 -080049extern char RemapShorty(char shortyType);
Shih-wei Liaob2596522012-09-14 16:36:11 -070050};
51
Shih-wei Liao21d28f52012-06-12 05:55:00 -070052namespace {
53
54class GBCExpanderPass : public llvm::FunctionPass {
55 private:
56 const IntrinsicHelper& intrinsic_helper_;
57 IRBuilder& irb_;
58
59 llvm::LLVMContext& context_;
60 RuntimeSupportBuilder& rtb_;
61
62 private:
63 llvm::AllocaInst* shadow_frame_;
64 llvm::Value* old_shadow_frame_;
Shih-wei Liao21d28f52012-06-12 05:55:00 -070065
66 private:
TDYa127920be7c2012-09-10 17:13:22 -070067 art::Compiler* compiler_;
TDYa1275e869b62012-07-25 00:45:39 -070068
TDYa127920be7c2012-09-10 17:13:22 -070069 const art::DexFile* dex_file_;
70 const art::DexFile::CodeItem* code_item_;
TDYa1275e869b62012-07-25 00:45:39 -070071
TDYa127920be7c2012-09-10 17:13:22 -070072 art::OatCompilationUnit* oat_compilation_unit_;
TDYa1275e869b62012-07-25 00:45:39 -070073
74 uint32_t method_idx_;
75
76 llvm::Function* func_;
77
78 std::vector<llvm::BasicBlock*> basic_blocks_;
79
80 std::vector<llvm::BasicBlock*> basic_block_landing_pads_;
TDYa12755e5e6c2012-09-11 15:14:42 -070081 llvm::BasicBlock* current_bb_;
TDYa127aa558872012-08-16 05:11:07 -070082 std::map<llvm::BasicBlock*, std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*> > >
83 landing_pad_phi_mapping_;
TDYa1275e869b62012-07-25 00:45:39 -070084 llvm::BasicBlock* basic_block_unwind_;
85
Logan Chien67645d82012-08-17 09:10:54 +080086 bool changed_;
87
TDYa1275e869b62012-07-25 00:45:39 -070088 private:
Shih-wei Liao21d28f52012-06-12 05:55:00 -070089 //----------------------------------------------------------------------------
Logan Chien75e4b602012-07-23 14:24:12 -070090 // Constant for GBC expansion
91 //----------------------------------------------------------------------------
92 enum IntegerShiftKind {
93 kIntegerSHL,
94 kIntegerSHR,
95 kIntegerUSHR,
96 };
97
98 private:
99 //----------------------------------------------------------------------------
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700100 // Helper function for GBC expansion
101 //----------------------------------------------------------------------------
102
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700103 llvm::Value* ExpandToRuntime(runtime_support::RuntimeId rt,
104 llvm::CallInst& inst);
105
TDYa1275e869b62012-07-25 00:45:39 -0700106 uint64_t LV2UInt(llvm::Value* lv) {
107 return llvm::cast<llvm::ConstantInt>(lv)->getZExtValue();
108 }
109
110 int64_t LV2SInt(llvm::Value* lv) {
111 return llvm::cast<llvm::ConstantInt>(lv)->getSExtValue();
112 }
113
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700114 private:
115 // TODO: Almost all Emit* are directly copy-n-paste from MethodCompiler.
116 // Refactor these utility functions from MethodCompiler to avoid forking.
117
Logan Chien67645d82012-08-17 09:10:54 +0800118 void EmitStackOverflowCheck(llvm::Instruction* first_non_alloca);
119
120 void RewriteFunction();
121
122 void RewriteBasicBlock(llvm::BasicBlock* original_block);
123
124 void UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
125 llvm::BasicBlock* new_basic_block);
126
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700127
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800128 // Sign or zero extend category 1 types < 32bits in size to 32bits.
129 llvm::Value* SignOrZeroExtendCat1Types(llvm::Value* value, JType jty);
130
131 // Truncate category 1 types from 32bits to the given JType size.
132 llvm::Value* TruncateCat1Types(llvm::Value* value, JType jty);
133
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700134 //----------------------------------------------------------------------------
135 // Dex cache code generation helper function
136 //----------------------------------------------------------------------------
TDYa127920be7c2012-09-10 17:13:22 -0700137 llvm::Value* EmitLoadDexCacheAddr(art::MemberOffset dex_cache_offset);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700138
139 llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
140
141 llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
142
143 llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
144
145 llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
146
147 //----------------------------------------------------------------------------
148 // Code generation helper function
149 //----------------------------------------------------------------------------
150 llvm::Value* EmitLoadMethodObjectAddr();
151
152 llvm::Value* EmitLoadArrayLength(llvm::Value* array);
153
154 llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
155
156 llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
157 llvm::Value* this_addr);
158
159 llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
160 llvm::Value* index_value,
161 JType elem_jty);
162
163 private:
164 //----------------------------------------------------------------------------
165 // Expand Greenland intrinsics
166 //----------------------------------------------------------------------------
167 void Expand_TestSuspend(llvm::CallInst& call_inst);
168
TDYa1279a129452012-07-19 03:10:08 -0700169 void Expand_MarkGCCard(llvm::CallInst& call_inst);
170
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700171 llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
172
173 llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
174
175 void Expand_LockObject(llvm::Value* obj);
176
177 void Expand_UnlockObject(llvm::Value* obj);
178
179 llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
180 llvm::Value* index_value,
181 JType elem_jty);
182
183 void Expand_ArrayPut(llvm::Value* new_value,
184 llvm::Value* array_addr,
185 llvm::Value* index_value,
186 JType elem_jty);
187
188 void Expand_FilledNewArray(llvm::CallInst& call_inst);
189
190 llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
191 llvm::Value* is_volatile_value,
192 llvm::Value* object_addr,
193 JType field_jty);
194
195 void Expand_IPutFast(llvm::Value* field_offset_value,
196 llvm::Value* is_volatile_value,
197 llvm::Value* object_addr,
198 llvm::Value* new_value,
199 JType field_jty);
200
201 llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
202 llvm::Value* field_offset_value,
203 llvm::Value* is_volatile_value,
204 JType field_jty);
205
206 void Expand_SPutFast(llvm::Value* static_storage_addr,
207 llvm::Value* field_offset_value,
208 llvm::Value* is_volatile_value,
209 llvm::Value* new_value,
210 JType field_jty);
211
212 llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
213
214 llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
215
216 llvm::Value*
217 Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
218
219 llvm::Value*
220 Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
221 llvm::Value* this_addr);
222
223 llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
224
TDYa1274ec8ccd2012-08-11 07:04:57 -0700225 llvm::Value* Expand_DivRem(llvm::CallInst& call_inst, bool is_div, JType op_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700226
TDYa127ce4cc0d2012-11-18 16:59:53 -0800227 void Expand_AllocaShadowFrame(llvm::Value* num_vregs_value);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700228
TDYa1278e950c12012-11-02 09:58:19 -0700229 void Expand_SetVReg(llvm::Value* entry_idx, llvm::Value* obj);
230
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700231 void Expand_PopShadowFrame();
232
233 void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
234
TDYa127a1b21852012-07-23 03:20:39 -0700235 //----------------------------------------------------------------------------
236 // Quick
237 //----------------------------------------------------------------------------
238
239 llvm::Value* Expand_FPCompare(llvm::Value* src1_value,
240 llvm::Value* src2_value,
241 bool gt_bias);
242
243 llvm::Value* Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value);
244
245 llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
246 llvm::Value* cmp_lt);
247
TDYa127f71bf5a2012-07-29 20:09:52 -0700248 llvm::Value* EmitLoadConstantClass(uint32_t dex_pc, uint32_t type_idx);
TDYa1275a26d442012-07-26 18:58:38 -0700249 llvm::Value* EmitLoadStaticStorage(uint32_t dex_pc, uint32_t type_idx);
250
TDYa1275e869b62012-07-25 00:45:39 -0700251 llvm::Value* Expand_HLIGet(llvm::CallInst& call_inst, JType field_jty);
252 void Expand_HLIPut(llvm::CallInst& call_inst, JType field_jty);
253
TDYa1275a26d442012-07-26 18:58:38 -0700254 llvm::Value* Expand_HLSget(llvm::CallInst& call_inst, JType field_jty);
255 void Expand_HLSput(llvm::CallInst& call_inst, JType field_jty);
256
257 llvm::Value* Expand_HLArrayGet(llvm::CallInst& call_inst, JType field_jty);
258 void Expand_HLArrayPut(llvm::CallInst& call_inst, JType field_jty);
259
TDYa127f71bf5a2012-07-29 20:09:52 -0700260 llvm::Value* Expand_ConstString(llvm::CallInst& call_inst);
261 llvm::Value* Expand_ConstClass(llvm::CallInst& call_inst);
262
263 void Expand_MonitorEnter(llvm::CallInst& call_inst);
264 void Expand_MonitorExit(llvm::CallInst& call_inst);
265
266 void Expand_HLCheckCast(llvm::CallInst& call_inst);
267 llvm::Value* Expand_InstanceOf(llvm::CallInst& call_inst);
268
269 llvm::Value* Expand_NewInstance(llvm::CallInst& call_inst);
270
271 llvm::Value* Expand_HLInvoke(llvm::CallInst& call_inst);
272
273 llvm::Value* Expand_OptArrayLength(llvm::CallInst& call_inst);
274 llvm::Value* Expand_NewArray(llvm::CallInst& call_inst);
275 llvm::Value* Expand_HLFilledNewArray(llvm::CallInst& call_inst);
276 void Expand_HLFillArrayData(llvm::CallInst& call_inst);
277
278 llvm::Value* EmitAllocNewArray(uint32_t dex_pc,
279 llvm::Value* array_length_value,
280 uint32_t type_idx,
281 bool is_filled_new_array);
282
283 llvm::Value* EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
TDYa127920be7c2012-09-10 17:13:22 -0700284 art::InvokeType invoke_type,
TDYa127f71bf5a2012-07-29 20:09:52 -0700285 llvm::Value* this_addr,
286 uint32_t dex_pc,
287 bool is_fast_path);
288
TDYa1275e869b62012-07-25 00:45:39 -0700289 void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
290
291 void EmitUpdateDexPC(uint32_t dex_pc);
292
293 void EmitGuard_DivZeroException(uint32_t dex_pc,
294 llvm::Value* denominator,
295 JType op_jty);
296
297 void EmitGuard_NullPointerException(uint32_t dex_pc,
298 llvm::Value* object);
299
300 void EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
301 llvm::Value* array,
302 llvm::Value* index);
303
TDYa1275e869b62012-07-25 00:45:39 -0700304 llvm::FunctionType* GetFunctionType(uint32_t method_idx, bool is_static);
305
306 llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
307
308 llvm::BasicBlock* CreateBasicBlockWithDexPC(uint32_t dex_pc,
309 const char* postfix);
310
311 int32_t GetTryItemOffset(uint32_t dex_pc);
312
313 llvm::BasicBlock* GetLandingPadBasicBlock(uint32_t dex_pc);
314
315 llvm::BasicBlock* GetUnwindBasicBlock();
316
317 void EmitGuard_ExceptionLandingPad(uint32_t dex_pc);
318
319 void EmitBranchExceptionLandingPad(uint32_t dex_pc);
320
Logan Chien75e4b602012-07-23 14:24:12 -0700321 //----------------------------------------------------------------------------
322 // Expand Arithmetic Helper Intrinsics
323 //----------------------------------------------------------------------------
324
325 llvm::Value* Expand_IntegerShift(llvm::Value* src1_value,
326 llvm::Value* src2_value,
327 IntegerShiftKind kind,
328 JType op_jty);
329
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700330 public:
331 static char ID;
332
333 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb)
334 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
Logan Chiene5b8f8b2012-08-13 11:45:05 +0800335 context_(irb.getContext()), rtb_(irb.Runtime()),
TDYa1278e950c12012-11-02 09:58:19 -0700336 shadow_frame_(NULL), old_shadow_frame_(NULL),
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700337 compiler_(NULL), dex_file_(NULL), code_item_(NULL),
Logan Chien67645d82012-08-17 09:10:54 +0800338 oat_compilation_unit_(NULL), method_idx_(-1u), func_(NULL),
339 changed_(false)
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700340 { }
341
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700342 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
TDYa127920be7c2012-09-10 17:13:22 -0700343 art::Compiler* compiler, art::OatCompilationUnit* oat_compilation_unit)
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700344 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
345 context_(irb.getContext()), rtb_(irb.Runtime()),
TDYa1278e950c12012-11-02 09:58:19 -0700346 shadow_frame_(NULL), old_shadow_frame_(NULL),
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700347 compiler_(compiler),
348 dex_file_(oat_compilation_unit->GetDexFile()),
349 code_item_(oat_compilation_unit->GetCodeItem()),
350 oat_compilation_unit_(oat_compilation_unit),
351 method_idx_(oat_compilation_unit->GetDexMethodIndex()),
352 func_(NULL), changed_(false)
353 { }
354
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700355 bool runOnFunction(llvm::Function& func);
356
357 private:
Logan Chien67645d82012-08-17 09:10:54 +0800358 void InsertStackOverflowCheck(llvm::Function& func);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700359
360 llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
361 llvm::CallInst& call_inst);
362
363};
364
365char GBCExpanderPass::ID = 0;
366
367bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
TDYa127b672d1e2012-06-28 21:21:45 -0700368 // Runtime support or stub
369 if (func.getName().startswith("art_") || func.getName().startswith("Art")) {
370 return false;
371 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700372
Logan Chien67645d82012-08-17 09:10:54 +0800373 // Setup rewrite context
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700374 shadow_frame_ = NULL;
375 old_shadow_frame_ = NULL;
TDYa1275e869b62012-07-25 00:45:39 -0700376 func_ = &func;
Logan Chien67645d82012-08-17 09:10:54 +0800377 changed_ = false; // Assume unchanged
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700378
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700379 basic_blocks_.resize(code_item_->insns_size_in_code_units_);
380 basic_block_landing_pads_.resize(code_item_->tries_size_, NULL);
381 basic_block_unwind_ = NULL;
382 for (llvm::Function::iterator bb_iter = func_->begin(), bb_end = func_->end();
383 bb_iter != bb_end;
384 ++bb_iter) {
385 if (bb_iter->begin()->getMetadata("DexOff") == NULL) {
386 continue;
387 }
388 uint32_t dex_pc = LV2UInt(bb_iter->begin()->getMetadata("DexOff")->getOperand(0));
389 basic_blocks_[dex_pc] = bb_iter;
390 }
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700391
Logan Chien67645d82012-08-17 09:10:54 +0800392 // Insert stack overflow check
393 InsertStackOverflowCheck(func); // TODO: Use intrinsic.
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700394
Logan Chien67645d82012-08-17 09:10:54 +0800395 // Rewrite the intrinsics
396 RewriteFunction();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700397
398 VERIFY_LLVM_FUNCTION(func);
399
Logan Chien67645d82012-08-17 09:10:54 +0800400 return changed_;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700401}
402
Logan Chien67645d82012-08-17 09:10:54 +0800403void GBCExpanderPass::RewriteBasicBlock(llvm::BasicBlock* original_block) {
404 llvm::BasicBlock* curr_basic_block = original_block;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700405
Logan Chien67645d82012-08-17 09:10:54 +0800406 llvm::BasicBlock::iterator inst_iter = original_block->begin();
407 llvm::BasicBlock::iterator inst_end = original_block->end();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700408
Logan Chien67645d82012-08-17 09:10:54 +0800409 while (inst_iter != inst_end) {
410 llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst_iter);
411 IntrinsicHelper::IntrinsicId intr_id = IntrinsicHelper::UnknownId;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700412
Logan Chien67645d82012-08-17 09:10:54 +0800413 if (call_inst) {
414 llvm::Function* callee_func = call_inst->getCalledFunction();
415 intr_id = intrinsic_helper_.GetIntrinsicId(callee_func);
416 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700417
Logan Chien67645d82012-08-17 09:10:54 +0800418 if (intr_id == IntrinsicHelper::UnknownId) {
419 // This is not intrinsic call. Skip this instruction.
420 ++inst_iter;
421 continue;
422 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700423
Logan Chien67645d82012-08-17 09:10:54 +0800424 // Rewrite the intrinsic and change the function
425 changed_ = true;
426 irb_.SetInsertPoint(inst_iter);
427
428 // Expand the intrinsic
429 if (llvm::Value* new_value = ExpandIntrinsic(intr_id, *call_inst)) {
430 inst_iter->replaceAllUsesWith(new_value);
431 }
432
433 // Remove the old intrinsic call instruction
434 llvm::BasicBlock::iterator old_inst = inst_iter++;
435 old_inst->eraseFromParent();
436
437 // Splice the instruction to the new basic block
438 llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
439 if (next_basic_block != curr_basic_block) {
440 next_basic_block->getInstList().splice(
441 irb_.GetInsertPoint(), curr_basic_block->getInstList(),
442 inst_iter, inst_end);
443 curr_basic_block = next_basic_block;
444 inst_end = curr_basic_block->end();
445 }
446 }
447}
448
449
450void GBCExpanderPass::RewriteFunction() {
451 size_t num_basic_blocks = func_->getBasicBlockList().size();
452 // NOTE: We are not using (bb_iter != bb_end) as the for-loop condition,
453 // because we will create new basic block while expanding the intrinsics.
454 // We only want to iterate through the input basic blocks.
455
TDYa127aa558872012-08-16 05:11:07 -0700456 landing_pad_phi_mapping_.clear();
457
Logan Chien67645d82012-08-17 09:10:54 +0800458 for (llvm::Function::iterator bb_iter = func_->begin();
459 num_basic_blocks > 0; ++bb_iter, --num_basic_blocks) {
Shih-wei Liao627d8c42012-08-24 08:31:18 -0700460 // Set insert point to current basic block.
461 irb_.SetInsertPoint(bb_iter);
Logan Chien67645d82012-08-17 09:10:54 +0800462
TDYa12755e5e6c2012-09-11 15:14:42 -0700463 current_bb_ = bb_iter;
TDYa127aa558872012-08-16 05:11:07 -0700464
Logan Chien67645d82012-08-17 09:10:54 +0800465 // Rewrite the basic block
466 RewriteBasicBlock(bb_iter);
467
468 // Update the phi-instructions in the successor basic block
469 llvm::BasicBlock* last_block = irb_.GetInsertBlock();
470 if (last_block != bb_iter) {
471 UpdatePhiInstruction(bb_iter, last_block);
472 }
473 }
TDYa127aa558872012-08-16 05:11:07 -0700474
475 typedef std::map<llvm::PHINode*, llvm::PHINode*> HandlerPHIMap;
476 HandlerPHIMap handler_phi;
477 // Iterate every used landing pad basic block
478 for (size_t i = 0, ei = basic_block_landing_pads_.size(); i != ei; ++i) {
479 llvm::BasicBlock* lbb = basic_block_landing_pads_[i];
480 if (lbb == NULL) {
481 continue;
482 }
483
484 llvm::TerminatorInst* term_inst = lbb->getTerminator();
485 std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*> >& rewrite_pair
486 = landing_pad_phi_mapping_[lbb];
487 irb_.SetInsertPoint(lbb->begin());
488
489 // Iterate every succeeding basic block (catch block)
490 for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
491 succ_iter != succ_end; ++succ_iter) {
492 llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
493
494 // Iterate every phi instructions in the succeeding basic block
495 for (llvm::BasicBlock::iterator
496 inst_iter = succ_basic_block->begin(),
497 inst_end = succ_basic_block->end();
498 inst_iter != inst_end; ++inst_iter) {
499 llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
500
501 if (!phi) {
502 break; // Meet non-phi instruction. Done.
503 }
504
505 if (handler_phi[phi] == NULL) {
506 handler_phi[phi] = llvm::PHINode::Create(phi->getType(), 1);
507 }
508
509 // Create new_phi in landing pad
510 llvm::PHINode* new_phi = irb_.CreatePHI(phi->getType(), rewrite_pair.size());
511 // Insert all incoming value into new_phi by rewrite_pair
512 for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
513 llvm::BasicBlock* old_bb = rewrite_pair[j].first;
514 llvm::BasicBlock* new_bb = rewrite_pair[j].second;
515 new_phi->addIncoming(phi->getIncomingValueForBlock(old_bb), new_bb);
516 }
517 // Delete all incoming value from phi by rewrite_pair
518 for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
519 llvm::BasicBlock* old_bb = rewrite_pair[j].first;
520 int old_bb_idx = phi->getBasicBlockIndex(old_bb);
521 if (old_bb_idx >= 0) {
522 phi->removeIncomingValue(old_bb_idx, false);
523 }
524 }
525 // Insert new_phi into new handler phi
526 handler_phi[phi]->addIncoming(new_phi, lbb);
527 }
528 }
529 }
530
531 // Replace all handler phi
532 // We can't just use the old handler phi, because some exception edges will disappear after we
533 // compute fast-path.
534 for (HandlerPHIMap::iterator it = handler_phi.begin(); it != handler_phi.end(); ++it) {
535 llvm::PHINode* old_phi = it->first;
536 llvm::PHINode* new_phi = it->second;
537 new_phi->insertBefore(old_phi);
538 old_phi->replaceAllUsesWith(new_phi);
539 old_phi->eraseFromParent();
540 }
Logan Chien67645d82012-08-17 09:10:54 +0800541}
542
543void GBCExpanderPass::UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
544 llvm::BasicBlock* new_basic_block) {
545 llvm::TerminatorInst* term_inst = new_basic_block->getTerminator();
546
547 if (!term_inst) {
548 return; // No terminating instruction in new_basic_block. Nothing to do.
549 }
550
551 // Iterate every succeeding basic block
552 for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
553 succ_iter != succ_end; ++succ_iter) {
554 llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
555
556 // Iterate every phi instructions in the succeeding basic block
557 for (llvm::BasicBlock::iterator
558 inst_iter = succ_basic_block->begin(),
559 inst_end = succ_basic_block->end();
560 inst_iter != inst_end; ++inst_iter) {
561 llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
562
563 if (!phi) {
564 break; // Meet non-phi instruction. Done.
565 }
566
567 // Update the incoming block of this phi instruction
568 for (llvm::PHINode::block_iterator
569 ibb_iter = phi->block_begin(), ibb_end = phi->block_end();
570 ibb_iter != ibb_end; ++ibb_iter) {
571 if (*ibb_iter == old_basic_block) {
572 *ibb_iter = new_basic_block;
573 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700574 }
575 }
576 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700577}
578
579llvm::Value* GBCExpanderPass::ExpandToRuntime(runtime_support::RuntimeId rt,
580 llvm::CallInst& inst) {
581 // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
582 // the arguments passed to the GBC intrinsic are as the same as IBC runtime
583 // function, therefore only called function is needed to change.
584 unsigned num_args = inst.getNumArgOperands();
585
586 if (num_args <= 0) {
587 return irb_.CreateCall(irb_.GetRuntime(rt));
588 } else {
589 std::vector<llvm::Value*> args;
590 for (unsigned i = 0; i < num_args; i++) {
591 args.push_back(inst.getArgOperand(i));
592 }
593
594 return irb_.CreateCall(irb_.GetRuntime(rt), args);
595 }
596}
597
Logan Chien67645d82012-08-17 09:10:54 +0800598void
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700599GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
600 llvm::Function* func = first_non_alloca->getParent()->getParent();
601 llvm::Module* module = func->getParent();
602
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700603 // Call llvm intrinsic function to get frame address.
604 llvm::Function* frameaddress =
605 llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
606
607 // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
608 llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
609
610 // Cast i8* to int
611 frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
612
613 // Get thread.stack_end_
614 llvm::Value* stack_end =
TDYa127920be7c2012-09-10 17:13:22 -0700615 irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::StackEndOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700616 irb_.getPtrEquivIntTy(),
617 kTBAARuntimeInfo);
618
619 // Check the frame address < thread.stack_end_ ?
620 llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
621
622 llvm::BasicBlock* block_exception =
623 llvm::BasicBlock::Create(context_, "stack_overflow", func);
624
625 llvm::BasicBlock* block_continue =
626 llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
627
628 irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
629
630 // If stack overflow, throw exception.
631 irb_.SetInsertPoint(block_exception);
632 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowStackOverflowException));
633
634 // Unwind.
635 llvm::Type* ret_type = func->getReturnType();
636 if (ret_type->isVoidTy()) {
637 irb_.CreateRetVoid();
638 } else {
639 // The return value is ignored when there's an exception. MethodCompiler
640 // returns zero value under the the corresponding return type in this case.
641 // GBCExpander returns LLVM undef value here for brevity
642 irb_.CreateRet(llvm::UndefValue::get(ret_type));
643 }
644
645 irb_.SetInsertPoint(block_continue);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700646}
647
TDYa127920be7c2012-09-10 17:13:22 -0700648llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(art::MemberOffset offset) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700649 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
650
651 return irb_.LoadFromObjectOffset(method_object_addr,
652 offset.Int32Value(),
653 irb_.getJObjectTy(),
654 kTBAAConstJObject);
655}
656
657llvm::Value*
658GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
659 llvm::Value* static_storage_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800660 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700661
662 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
663
664 return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
665}
666
667llvm::Value*
668GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
669 llvm::Value* resolved_type_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800670 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedTypesOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700671
672 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
673
674 return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
675}
676
677llvm::Value* GBCExpanderPass::
678EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
679 llvm::Value* resolved_method_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800680 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedMethodsOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700681
682 llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
683
684 return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
685}
686
687llvm::Value* GBCExpanderPass::
688EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
689 llvm::Value* string_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800690 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheStringsOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700691
692 llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
693
694 return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
695}
696
697llvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
698 llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
699 return parent_func->arg_begin();
700}
701
702llvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
703 // Load array length
704 return irb_.LoadFromObjectOffset(array,
Ian Rogers98573f92013-01-30 17:26:32 -0800705 art::mirror::Array::LengthOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700706 irb_.getJIntTy(),
707 kTBAAConstJObject);
708
709}
710
711llvm::Value*
712GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
713 llvm::Value* callee_method_object_field_addr =
714 EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
715
TDYa127ce4cc0d2012-11-18 16:59:53 -0800716 return irb_.CreateLoad(callee_method_object_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700717}
718
719llvm::Value* GBCExpanderPass::
720EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
721 // Load class object of *this* pointer
722 llvm::Value* class_object_addr =
723 irb_.LoadFromObjectOffset(this_addr,
Ian Rogers98573f92013-01-30 17:26:32 -0800724 art::mirror::Object::ClassOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700725 irb_.getJObjectTy(),
726 kTBAAConstJObject);
727
728 // Load vtable address
729 llvm::Value* vtable_addr =
730 irb_.LoadFromObjectOffset(class_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -0800731 art::mirror::Class::VTableOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700732 irb_.getJObjectTy(),
733 kTBAAConstJObject);
734
735 // Load callee method object
736 llvm::Value* vtable_idx_value =
737 irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
738
739 llvm::Value* method_field_addr =
740 EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
741
742 return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
743}
744
745// Emit Array GetElementPtr
746llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
747 llvm::Value* index_value,
748 JType elem_jty) {
749
750 int data_offset;
751 if (elem_jty == kLong || elem_jty == kDouble ||
Ian Rogers98573f92013-01-30 17:26:32 -0800752 (elem_jty == kObject && sizeof(uint64_t) == sizeof(art::mirror::Object*))) {
753 data_offset = art::mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700754 } else {
Ian Rogers98573f92013-01-30 17:26:32 -0800755 data_offset = art::mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700756 }
757
758 llvm::Constant* data_offset_value =
759 irb_.getPtrEquivInt(data_offset);
760
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800761 llvm::Type* elem_type = irb_.getJType(elem_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700762
763 llvm::Value* array_data_addr =
764 irb_.CreatePtrDisp(array_addr, data_offset_value,
765 elem_type->getPointerTo());
766
767 return irb_.CreateGEP(array_data_addr, index_value);
768}
769
770void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
TDYa127ce4cc0d2012-11-18 16:59:53 -0800771 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
772
773 llvm::Value* suspend_count =
774 irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::ThreadFlagsOffset().Int32Value(),
775 irb_.getInt16Ty(),
776 kTBAARuntimeInfo);
777 llvm::Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
778
779 llvm::BasicBlock* basic_block_suspend = CreateBasicBlockWithDexPC(dex_pc, "suspend");
780 llvm::BasicBlock* basic_block_cont = CreateBasicBlockWithDexPC(dex_pc, "suspend_cont");
781
782 irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
783
784 irb_.SetInsertPoint(basic_block_suspend);
785 if (dex_pc != art::DexFile::kDexNoIndex) {
786 EmitUpdateDexPC(dex_pc);
787 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700788 irb_.Runtime().EmitTestSuspend();
Jeff Hao11ffc2d2013-02-01 11:52:17 -0800789
790 llvm::BasicBlock* basic_block_exception = CreateBasicBlockWithDexPC(dex_pc, "exception");
791 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
792 irb_.CreateCondBr(exception_pending, basic_block_exception, basic_block_cont, kUnlikely);
793
794 irb_.SetInsertPoint(basic_block_exception);
795 llvm::Type* ret_type = call_inst.getParent()->getParent()->getReturnType();
796 if (ret_type->isVoidTy()) {
797 irb_.CreateRetVoid();
798 } else {
799 // The return value is ignored when there's an exception.
800 irb_.CreateRet(llvm::UndefValue::get(ret_type));
801 }
TDYa127ce4cc0d2012-11-18 16:59:53 -0800802
803 irb_.SetInsertPoint(basic_block_cont);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700804 return;
805}
806
TDYa1279a129452012-07-19 03:10:08 -0700807void GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
TDYa1279a129452012-07-19 03:10:08 -0700808 irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
TDYa1279a129452012-07-19 03:10:08 -0700809 return;
810}
811
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700812llvm::Value*
813GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
814 uint32_t string_idx =
815 llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
816
817 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
818
TDYa127ce4cc0d2012-11-18 16:59:53 -0800819 return irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700820}
821
822llvm::Value*
823GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
824 uint32_t type_idx =
825 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
826
827 llvm::Value* type_field_addr =
828 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
829
TDYa127ce4cc0d2012-11-18 16:59:53 -0800830 return irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700831}
832
833void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700834 rtb_.EmitLockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700835 return;
836}
837
838void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700839 rtb_.EmitUnlockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700840 return;
841}
842
843llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
844 llvm::Value* index_value,
845 JType elem_jty) {
846 llvm::Value* array_elem_addr =
847 EmitArrayGEP(array_addr, index_value, elem_jty);
848
849 return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
850}
851
852void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
853 llvm::Value* array_addr,
854 llvm::Value* index_value,
855 JType elem_jty) {
856 llvm::Value* array_elem_addr =
857 EmitArrayGEP(array_addr, index_value, elem_jty);
858
859 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
860
861 return;
862}
863
864void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
865 // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
866 llvm::Value* array = call_inst.getArgOperand(0);
867
868 uint32_t element_jty =
869 llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
870
871 DCHECK(call_inst.getNumArgOperands() > 2);
872 unsigned num_elements = (call_inst.getNumArgOperands() - 2);
873
874 bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
875
876 uint32_t alignment;
877 llvm::Constant* elem_size;
878 llvm::PointerType* field_type;
879
880 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
881 // as the element, thus we are only checking 2 cases: primitive int and
882 // non-primitive type.
883 if (is_elem_int_ty) {
884 alignment = sizeof(int32_t);
885 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
886 field_type = irb_.getJIntTy()->getPointerTo();
887 } else {
888 alignment = irb_.getSizeOfPtrEquivInt();
889 elem_size = irb_.getSizeOfPtrEquivIntValue();
890 field_type = irb_.getJObjectTy()->getPointerTo();
891 }
892
893 llvm::Value* data_field_offset =
Ian Rogers98573f92013-01-30 17:26:32 -0800894 irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700895
896 llvm::Value* data_field_addr =
897 irb_.CreatePtrDisp(array, data_field_offset, field_type);
898
899 for (unsigned i = 0; i < num_elements; ++i) {
900 // Values to fill the array begin at the 3rd argument
901 llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
902
903 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
904
905 data_field_addr =
906 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
907 }
908
909 return;
910}
911
912llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
913 llvm::Value* /*is_volatile_value*/,
914 llvm::Value* object_addr,
915 JType field_jty) {
916 int field_offset =
917 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
918
919 DCHECK_GE(field_offset, 0);
920
921 llvm::PointerType* field_type =
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800922 irb_.getJType(field_jty)->getPointerTo();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700923
924 field_offset_value = irb_.getPtrEquivInt(field_offset);
925
926 llvm::Value* field_addr =
927 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
928
929 // TODO: Check is_volatile. We need to generate atomic load instruction
930 // when is_volatile is true.
931 return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
932}
933
934void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
935 llvm::Value* /* is_volatile_value */,
936 llvm::Value* object_addr,
937 llvm::Value* new_value,
938 JType field_jty) {
939 int field_offset =
940 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
941
942 DCHECK_GE(field_offset, 0);
943
944 llvm::PointerType* field_type =
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800945 irb_.getJType(field_jty)->getPointerTo();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700946
947 field_offset_value = irb_.getPtrEquivInt(field_offset);
948
949 llvm::Value* field_addr =
950 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
951
952 // TODO: Check is_volatile. We need to generate atomic store instruction
953 // when is_volatile is true.
954 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
955
956 return;
957}
958
959llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
960 llvm::Value* field_offset_value,
961 llvm::Value* /*is_volatile_value*/,
962 JType field_jty) {
963 int field_offset =
964 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
965
966 DCHECK_GE(field_offset, 0);
967
968 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
969
970 llvm::Value* static_field_addr =
971 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800972 irb_.getJType(field_jty)->getPointerTo());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700973
974 // TODO: Check is_volatile. We need to generate atomic store instruction
975 // when is_volatile is true.
976 return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
977}
978
979void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
980 llvm::Value* field_offset_value,
981 llvm::Value* /* is_volatile_value */,
982 llvm::Value* new_value,
983 JType field_jty) {
984 int field_offset =
985 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
986
987 DCHECK_GE(field_offset, 0);
988
989 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
990
991 llvm::Value* static_field_addr =
992 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
Ian Rogers76ae4fe2013-02-27 16:03:41 -0800993 irb_.getJType(field_jty)->getPointerTo());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700994
995 // TODO: Check is_volatile. We need to generate atomic store instruction
996 // when is_volatile is true.
997 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
998
999 return;
1000}
1001
1002llvm::Value*
1003GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
1004 return irb_.LoadFromObjectOffset(method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001005 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001006 irb_.getJObjectTy(),
1007 kTBAAConstJObject);
1008}
1009
1010llvm::Value*
1011GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
1012 uint32_t type_idx =
1013 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
1014
1015 llvm::Value* storage_field_addr =
1016 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
1017
TDYa127ce4cc0d2012-11-18 16:59:53 -08001018 return irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001019}
1020
1021llvm::Value*
1022GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
1023 uint32_t callee_method_idx =
1024 llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
1025
1026 return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
1027}
1028
1029llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
1030 llvm::Value* vtable_idx_value,
1031 llvm::Value* this_addr) {
1032 int vtable_idx =
1033 llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
1034
1035 return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
1036}
1037
1038llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
1039 // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
1040 llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
1041 unsigned num_args = call_inst.getNumArgOperands();
1042 llvm::Type* ret_type = call_inst.getType();
1043
1044 // Determine the function type of the callee method
1045 std::vector<llvm::Type*> args_type;
1046 std::vector<llvm::Value*> args;
1047 for (unsigned i = 0; i < num_args; i++) {
1048 args.push_back(call_inst.getArgOperand(i));
1049 args_type.push_back(args[i]->getType());
1050 }
1051
1052 llvm::FunctionType* callee_method_type =
1053 llvm::FunctionType::get(ret_type, args_type, false);
1054
1055 llvm::Value* code_addr =
1056 irb_.LoadFromObjectOffset(callee_method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001057 art::mirror::AbstractMethod::GetCodeOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001058 callee_method_type->getPointerTo(),
TDYa127ce4cc0d2012-11-18 16:59:53 -08001059 kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001060
1061 // Invoke callee
1062 llvm::Value* retval = irb_.CreateCall(code_addr, args);
1063
1064 return retval;
1065}
1066
TDYa1274ec8ccd2012-08-11 07:04:57 -07001067llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::CallInst& call_inst,
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001068 bool is_div, JType op_jty) {
TDYa1274ec8ccd2012-08-11 07:04:57 -07001069 llvm::Value* dividend = call_inst.getArgOperand(0);
1070 llvm::Value* divisor = call_inst.getArgOperand(1);
TDYa1274ec8ccd2012-08-11 07:04:57 -07001071 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1072 EmitGuard_DivZeroException(dex_pc, divisor, op_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001073 // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
1074
1075 // Check the special case: MININT / -1 = MININT
1076 // That case will cause overflow, which is undefined behavior in llvm.
1077 // So we check the divisor is -1 or not, if the divisor is -1, we do
1078 // the special path to avoid undefined behavior.
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001079 llvm::Type* op_type = irb_.getJType(op_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001080 llvm::Value* zero = irb_.getJZero(op_jty);
1081 llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
1082
TDYa1275e869b62012-07-25 00:45:39 -07001083 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001084 llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
1085 llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
1086 llvm::BasicBlock* neg_one_cont =
1087 llvm::BasicBlock::Create(context_, "", parent);
1088
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001089 llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
1090 irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
1091
1092 // If divisor == -1
1093 irb_.SetInsertPoint(eq_neg_one);
1094 llvm::Value* eq_result;
1095 if (is_div) {
1096 // We can just change from "dividend div -1" to "neg dividend". The sub
1097 // don't care the sign/unsigned because of two's complement representation.
1098 // And the behavior is what we want:
1099 // -(2^n) (2^n)-1
1100 // MININT < k <= MAXINT -> mul k -1 = -k
1101 // MININT == k -> mul k -1 = k
1102 //
1103 // LLVM use sub to represent 'neg'
1104 eq_result = irb_.CreateSub(zero, dividend);
1105 } else {
1106 // Everything modulo -1 will be 0.
1107 eq_result = zero;
1108 }
1109 irb_.CreateBr(neg_one_cont);
1110
1111 // If divisor != -1, just do the division.
1112 irb_.SetInsertPoint(ne_neg_one);
1113 llvm::Value* ne_result;
1114 if (is_div) {
1115 ne_result = irb_.CreateSDiv(dividend, divisor);
1116 } else {
1117 ne_result = irb_.CreateSRem(dividend, divisor);
1118 }
1119 irb_.CreateBr(neg_one_cont);
1120
1121 irb_.SetInsertPoint(neg_one_cont);
1122 llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
1123 result->addIncoming(eq_result, eq_neg_one);
1124 result->addIncoming(ne_result, ne_neg_one);
1125
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001126 return result;
1127}
1128
TDYa127ce4cc0d2012-11-18 16:59:53 -08001129void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_vregs_value) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001130 // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
1131 // MethodCompiler::EmitPushShadowFrame
TDYa1278e950c12012-11-02 09:58:19 -07001132 uint16_t num_vregs =
1133 llvm::cast<llvm::ConstantInt>(num_vregs_value)->getZExtValue();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001134
1135 llvm::StructType* shadow_frame_type =
TDYa127ce4cc0d2012-11-18 16:59:53 -08001136 irb_.getShadowFrameTy(num_vregs);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001137
1138 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
1139
1140 // Alloca a pointer to old shadow frame
1141 old_shadow_frame_ =
1142 irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
1143
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001144 // Push the shadow frame
1145 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1146
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001147 llvm::Value* shadow_frame_upcast =
1148 irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
1149
1150 llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
1151 method_object_addr,
TDYa1278e950c12012-11-02 09:58:19 -07001152 num_vregs);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001153
1154 irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
1155
1156 return;
1157}
1158
TDYa1278e950c12012-11-02 09:58:19 -07001159void GBCExpanderPass::Expand_SetVReg(llvm::Value* entry_idx,
1160 llvm::Value* value) {
1161 DCHECK(shadow_frame_ != NULL);
1162
1163 llvm::Value* gep_index[] = {
1164 irb_.getInt32(0), // No pointer displacement
TDYa127ce4cc0d2012-11-18 16:59:53 -08001165 irb_.getInt32(1), // VRegs
TDYa1278e950c12012-11-02 09:58:19 -07001166 entry_idx // Pointer field
1167 };
1168
1169 llvm::Value* vreg_addr = irb_.CreateGEP(shadow_frame_, gep_index);
1170
1171 irb_.CreateStore(value,
1172 irb_.CreateBitCast(vreg_addr, value->getType()->getPointerTo()),
1173 kTBAAShadowFrame);
1174 return;
1175}
1176
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001177void GBCExpanderPass::Expand_PopShadowFrame() {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001178 if (old_shadow_frame_ == NULL) {
1179 return;
1180 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001181 rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
1182 return;
1183}
1184
1185void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
1186 irb_.StoreToObjectOffset(shadow_frame_,
TDYa127920be7c2012-09-10 17:13:22 -07001187 art::ShadowFrame::DexPCOffset(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001188 dex_pc_value,
1189 kTBAAShadowFrame);
1190 return;
1191}
1192
Logan Chien67645d82012-08-17 09:10:54 +08001193void GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
jeffhao40283122013-01-15 13:15:24 -08001194 // All alloca instructions are generated in the first basic block of the
1195 // function, and there are no alloca instructions after the first non-alloca
1196 // instruction.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001197
Logan Chien67645d82012-08-17 09:10:54 +08001198 llvm::BasicBlock* first_basic_block = &func.front();
1199
1200 // Look for first non-alloca instruction
1201 llvm::BasicBlock::iterator first_non_alloca = first_basic_block->begin();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001202 while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
1203 ++first_non_alloca;
1204 }
1205
Logan Chien67645d82012-08-17 09:10:54 +08001206 irb_.SetInsertPoint(first_non_alloca);
1207
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001208 // Insert stack overflow check codes before first_non_alloca (i.e., after all
1209 // alloca instructions)
Logan Chien67645d82012-08-17 09:10:54 +08001210 EmitStackOverflowCheck(&*first_non_alloca);
1211
TDYa127890ea892012-08-22 10:49:42 -07001212 irb_.Runtime().EmitTestSuspend();
TDYa127890ea892012-08-22 10:49:42 -07001213
Logan Chien67645d82012-08-17 09:10:54 +08001214 llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
1215 if (next_basic_block != first_basic_block) {
1216 // Splice the rest of the instruction to the continuing basic block
1217 next_basic_block->getInstList().splice(
1218 irb_.GetInsertPoint(), first_basic_block->getInstList(),
1219 first_non_alloca, first_basic_block->end());
1220
1221 // Rewrite the basic block
1222 RewriteBasicBlock(next_basic_block);
1223
1224 // Update the phi-instructions in the successor basic block
1225 UpdatePhiInstruction(first_basic_block, irb_.GetInsertBlock());
1226 }
1227
1228 // We have changed the basic block
1229 changed_ = true;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001230}
1231
TDYa1275e869b62012-07-25 00:45:39 -07001232// ==== High-level intrinsic expander ==========================================
1233
TDYa127a1b21852012-07-23 03:20:39 -07001234llvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
1235 llvm::Value* src2_value,
1236 bool gt_bias) {
1237 llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
1238 llvm::Value* cmp_lt;
1239
1240 if (gt_bias) {
1241 cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
1242 } else {
1243 cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
1244 }
1245
1246 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1247}
1248
1249llvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
1250 llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
1251 llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
1252
1253 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1254}
1255
1256llvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
1257 llvm::Value* cmp_lt) {
1258
1259 llvm::Constant* zero = irb_.getJInt(0);
1260 llvm::Constant* pos1 = irb_.getJInt(1);
1261 llvm::Constant* neg1 = irb_.getJInt(-1);
1262
1263 llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
1264 llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
1265
1266 return result_eq;
1267}
1268
Logan Chien75e4b602012-07-23 14:24:12 -07001269llvm::Value* GBCExpanderPass::Expand_IntegerShift(llvm::Value* src1_value,
1270 llvm::Value* src2_value,
1271 IntegerShiftKind kind,
1272 JType op_jty) {
1273 DCHECK(op_jty == kInt || op_jty == kLong);
1274
1275 // Mask and zero-extend RHS properly
1276 if (op_jty == kInt) {
1277 src2_value = irb_.CreateAnd(src2_value, 0x1f);
1278 } else {
1279 llvm::Value* masked_src2_value = irb_.CreateAnd(src2_value, 0x3f);
1280 src2_value = irb_.CreateZExt(masked_src2_value, irb_.getJLongTy());
1281 }
1282
1283 // Create integer shift llvm instruction
1284 switch (kind) {
1285 case kIntegerSHL:
1286 return irb_.CreateShl(src1_value, src2_value);
1287
1288 case kIntegerSHR:
1289 return irb_.CreateAShr(src1_value, src2_value);
1290
1291 case kIntegerUSHR:
1292 return irb_.CreateLShr(src1_value, src2_value);
1293
1294 default:
1295 LOG(FATAL) << "Unknown integer shift kind: " << kind;
1296 return NULL;
1297 }
1298}
1299
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001300llvm::Value* GBCExpanderPass::SignOrZeroExtendCat1Types(llvm::Value* value, JType jty) {
1301 switch (jty) {
1302 case kBoolean:
1303 case kChar:
1304 return irb_.CreateZExt(value, irb_.getJType(kInt));
1305 case kByte:
1306 case kShort:
1307 return irb_.CreateSExt(value, irb_.getJType(kInt));
1308 case kVoid:
1309 case kInt:
1310 case kLong:
1311 case kFloat:
1312 case kDouble:
1313 case kObject:
1314 return value; // Nothing to do.
1315 default:
1316 LOG(FATAL) << "Unknown java type: " << jty;
1317 return NULL;
1318 }
1319}
1320
1321llvm::Value* GBCExpanderPass::TruncateCat1Types(llvm::Value* value, JType jty) {
1322 switch (jty) {
1323 case kBoolean:
1324 case kChar:
1325 case kByte:
1326 case kShort:
1327 return irb_.CreateTrunc(value, irb_.getJType(jty));
1328 case kVoid:
1329 case kInt:
1330 case kLong:
1331 case kFloat:
1332 case kDouble:
1333 case kObject:
1334 return value; // Nothing to do.
1335 default:
1336 LOG(FATAL) << "Unknown java type: " << jty;
1337 return NULL;
1338 }
1339}
1340
TDYa1275a26d442012-07-26 18:58:38 -07001341llvm::Value* GBCExpanderPass::Expand_HLArrayGet(llvm::CallInst& call_inst,
1342 JType elem_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001343 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1344 llvm::Value* array_addr = call_inst.getArgOperand(1);
1345 llvm::Value* index_value = call_inst.getArgOperand(2);
TDYa127920be7c2012-09-10 17:13:22 -07001346 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275a26d442012-07-26 18:58:38 -07001347
TDYa127920be7c2012-09-10 17:13:22 -07001348 if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1349 EmitGuard_NullPointerException(dex_pc, array_addr);
1350 }
1351 if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) {
1352 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value);
1353 }
TDYa1275a26d442012-07-26 18:58:38 -07001354
1355 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1356
1357 llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
1358
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001359 return SignOrZeroExtendCat1Types(array_elem_value, elem_jty);
TDYa1275a26d442012-07-26 18:58:38 -07001360}
1361
1362
1363void GBCExpanderPass::Expand_HLArrayPut(llvm::CallInst& call_inst,
1364 JType elem_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001365 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1366 llvm::Value* new_value = call_inst.getArgOperand(1);
1367 llvm::Value* array_addr = call_inst.getArgOperand(2);
1368 llvm::Value* index_value = call_inst.getArgOperand(3);
TDYa127920be7c2012-09-10 17:13:22 -07001369 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275a26d442012-07-26 18:58:38 -07001370
TDYa127920be7c2012-09-10 17:13:22 -07001371 if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1372 EmitGuard_NullPointerException(dex_pc, array_addr);
1373 }
1374 if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) {
1375 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value);
1376 }
TDYa1275a26d442012-07-26 18:58:38 -07001377
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001378 new_value = TruncateCat1Types(new_value, elem_jty);
TDYa1275a26d442012-07-26 18:58:38 -07001379
1380 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1381
1382 if (elem_jty == kObject) { // If put an object, check the type, and mark GC card table.
1383 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::CheckPutArrayElement);
1384
1385 irb_.CreateCall2(runtime_func, new_value, array_addr);
1386
1387 EmitGuard_ExceptionLandingPad(dex_pc);
1388
1389 EmitMarkGCCard(new_value, array_addr);
1390 }
1391
1392 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
1393
1394 return;
1395}
1396
TDYa1275e869b62012-07-25 00:45:39 -07001397llvm::Value* GBCExpanderPass::Expand_HLIGet(llvm::CallInst& call_inst,
1398 JType field_jty) {
TDYa1275e869b62012-07-25 00:45:39 -07001399 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1400 llvm::Value* object_addr = call_inst.getArgOperand(1);
1401 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(2));
TDYa127920be7c2012-09-10 17:13:22 -07001402 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275e869b62012-07-25 00:45:39 -07001403
TDYa127920be7c2012-09-10 17:13:22 -07001404 if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1405 EmitGuard_NullPointerException(dex_pc, object_addr);
1406 }
TDYa1275e869b62012-07-25 00:45:39 -07001407
1408 llvm::Value* field_value;
1409
1410 int field_offset;
1411 bool is_volatile;
1412 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1413 field_idx, oat_compilation_unit_, field_offset, is_volatile, false);
1414
1415 if (!is_fast_path) {
1416 llvm::Function* runtime_func;
1417
1418 if (field_jty == kObject) {
1419 runtime_func = irb_.GetRuntime(runtime_support::GetObjectInstance);
1420 } else if (field_jty == kLong || field_jty == kDouble) {
1421 runtime_func = irb_.GetRuntime(runtime_support::Get64Instance);
1422 } else {
1423 runtime_func = irb_.GetRuntime(runtime_support::Get32Instance);
1424 }
1425
1426 llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
1427
1428 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1429
1430 EmitUpdateDexPC(dex_pc);
1431
1432 field_value = irb_.CreateCall3(runtime_func, field_idx_value,
1433 method_object_addr, object_addr);
1434
1435 EmitGuard_ExceptionLandingPad(dex_pc);
1436
1437 } else {
1438 DCHECK_GE(field_offset, 0);
1439
1440 llvm::PointerType* field_type =
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001441 irb_.getJType(field_jty)->getPointerTo();
TDYa1275e869b62012-07-25 00:45:39 -07001442
1443 llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
1444
1445 llvm::Value* field_addr =
1446 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1447
1448 // TODO: Check is_volatile. We need to generate atomic load instruction
1449 // when is_volatile is true.
1450 field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001451 field_value = SignOrZeroExtendCat1Types(field_value, field_jty);
TDYa1275e869b62012-07-25 00:45:39 -07001452 }
1453
1454 if (field_jty == kFloat || field_jty == kDouble) {
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001455 field_value = irb_.CreateBitCast(field_value, irb_.getJType(field_jty));
TDYa1275e869b62012-07-25 00:45:39 -07001456 }
1457
1458 return field_value;
1459}
1460
1461void GBCExpanderPass::Expand_HLIPut(llvm::CallInst& call_inst,
1462 JType field_jty) {
TDYa1275e869b62012-07-25 00:45:39 -07001463 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001464 llvm::Value* new_value = call_inst.getArgOperand(1);
1465 llvm::Value* object_addr = call_inst.getArgOperand(2);
TDYa1275e869b62012-07-25 00:45:39 -07001466 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(3));
TDYa127920be7c2012-09-10 17:13:22 -07001467 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275e869b62012-07-25 00:45:39 -07001468
1469 if (field_jty == kFloat || field_jty == kDouble) {
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001470 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty));
TDYa1275e869b62012-07-25 00:45:39 -07001471 }
1472
TDYa127920be7c2012-09-10 17:13:22 -07001473 if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1474 EmitGuard_NullPointerException(dex_pc, object_addr);
1475 }
TDYa1275e869b62012-07-25 00:45:39 -07001476
1477 int field_offset;
1478 bool is_volatile;
1479 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1480 field_idx, oat_compilation_unit_, field_offset, is_volatile, true);
1481
1482 if (!is_fast_path) {
1483 llvm::Function* runtime_func;
1484
1485 if (field_jty == kObject) {
1486 runtime_func = irb_.GetRuntime(runtime_support::SetObjectInstance);
1487 } else if (field_jty == kLong || field_jty == kDouble) {
1488 runtime_func = irb_.GetRuntime(runtime_support::Set64Instance);
1489 } else {
1490 runtime_func = irb_.GetRuntime(runtime_support::Set32Instance);
1491 }
1492
1493 llvm::Value* field_idx_value = irb_.getInt32(field_idx);
1494
1495 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1496
1497 EmitUpdateDexPC(dex_pc);
1498
1499 irb_.CreateCall4(runtime_func, field_idx_value,
1500 method_object_addr, object_addr, new_value);
1501
1502 EmitGuard_ExceptionLandingPad(dex_pc);
1503
1504 } else {
1505 DCHECK_GE(field_offset, 0);
1506
1507 llvm::PointerType* field_type =
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001508 irb_.getJType(field_jty)->getPointerTo();
TDYa1275e869b62012-07-25 00:45:39 -07001509
1510 llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
1511
1512 llvm::Value* field_addr =
1513 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1514
1515 // TODO: Check is_volatile. We need to generate atomic store instruction
1516 // when is_volatile is true.
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001517 new_value = TruncateCat1Types(new_value, field_jty);
TDYa1275e869b62012-07-25 00:45:39 -07001518 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
1519
1520 if (field_jty == kObject) { // If put an object, mark the GC card table.
1521 EmitMarkGCCard(new_value, object_addr);
1522 }
1523 }
1524
1525 return;
1526}
1527
TDYa127f71bf5a2012-07-29 20:09:52 -07001528llvm::Value* GBCExpanderPass::EmitLoadConstantClass(uint32_t dex_pc,
1529 uint32_t type_idx) {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001530 if (!compiler_->CanAccessTypeWithoutChecks(method_idx_, *dex_file_, type_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001531 llvm::Value* type_idx_value = irb_.getInt32(type_idx);
1532
1533 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1534
1535 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1536
1537 llvm::Function* runtime_func =
1538 irb_.GetRuntime(runtime_support::InitializeTypeAndVerifyAccess);
1539
1540 EmitUpdateDexPC(dex_pc);
1541
1542 llvm::Value* type_object_addr =
1543 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1544
1545 EmitGuard_ExceptionLandingPad(dex_pc);
1546
1547 return type_object_addr;
1548
1549 } else {
1550 // Try to load the class (type) object from the test cache.
1551 llvm::Value* type_field_addr =
1552 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
1553
TDYa127ce4cc0d2012-11-18 16:59:53 -08001554 llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
TDYa127f71bf5a2012-07-29 20:09:52 -07001555
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001556 if (compiler_->CanAssumeTypeIsPresentInDexCache(*dex_file_, type_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001557 return type_object_addr;
1558 }
1559
1560 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1561
1562 // Test whether class (type) object is in the dex cache or not
1563 llvm::Value* equal_null =
1564 irb_.CreateICmpEQ(type_object_addr, irb_.getJNull());
1565
1566 llvm::BasicBlock* block_cont =
1567 CreateBasicBlockWithDexPC(dex_pc, "cont");
1568
1569 llvm::BasicBlock* block_load_class =
1570 CreateBasicBlockWithDexPC(dex_pc, "load_class");
1571
1572 irb_.CreateCondBr(equal_null, block_load_class, block_cont, kUnlikely);
1573
1574 // Failback routine to load the class object
1575 irb_.SetInsertPoint(block_load_class);
1576
1577 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeType);
1578
1579 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1580
1581 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1582
1583 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1584
1585 EmitUpdateDexPC(dex_pc);
1586
1587 llvm::Value* loaded_type_object_addr =
1588 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1589
1590 EmitGuard_ExceptionLandingPad(dex_pc);
1591
1592 llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
1593
1594 irb_.CreateBr(block_cont);
1595
1596 // Now the class object must be loaded
1597 irb_.SetInsertPoint(block_cont);
1598
1599 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1600
1601 phi->addIncoming(type_object_addr, block_original);
1602 phi->addIncoming(loaded_type_object_addr, block_after_load_class);
1603
1604 return phi;
1605 }
1606}
1607
TDYa1275a26d442012-07-26 18:58:38 -07001608llvm::Value* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc,
1609 uint32_t type_idx) {
1610 llvm::BasicBlock* block_load_static =
1611 CreateBasicBlockWithDexPC(dex_pc, "load_static");
1612
1613 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
1614
1615 // Load static storage from dex cache
1616 llvm::Value* storage_field_addr =
1617 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
1618
TDYa127ce4cc0d2012-11-18 16:59:53 -08001619 llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
TDYa1275a26d442012-07-26 18:58:38 -07001620
1621 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1622
1623 // Test: Is the static storage of this class initialized?
1624 llvm::Value* equal_null =
1625 irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
1626
1627 irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely);
1628
1629 // Failback routine to load the class object
1630 irb_.SetInsertPoint(block_load_static);
1631
1632 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeStaticStorage);
1633
1634 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1635
1636 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1637
1638 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1639
1640 EmitUpdateDexPC(dex_pc);
1641
1642 llvm::Value* loaded_storage_object_addr =
1643 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1644
1645 EmitGuard_ExceptionLandingPad(dex_pc);
1646
1647 llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
1648
1649 irb_.CreateBr(block_cont);
1650
1651 // Now the class object must be loaded
1652 irb_.SetInsertPoint(block_cont);
1653
1654 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1655
1656 phi->addIncoming(storage_object_addr, block_original);
1657 phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
1658
1659 return phi;
1660}
1661
1662llvm::Value* GBCExpanderPass::Expand_HLSget(llvm::CallInst& call_inst,
1663 JType field_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001664 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1665 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1666
1667 int field_offset;
1668 int ssb_index;
1669 bool is_referrers_class;
1670 bool is_volatile;
1671
1672 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
1673 field_idx, oat_compilation_unit_, field_offset, ssb_index,
1674 is_referrers_class, is_volatile, false);
1675
1676 llvm::Value* static_field_value;
1677
1678 if (!is_fast_path) {
1679 llvm::Function* runtime_func;
1680
1681 if (field_jty == kObject) {
1682 runtime_func = irb_.GetRuntime(runtime_support::GetObjectStatic);
1683 } else if (field_jty == kLong || field_jty == kDouble) {
1684 runtime_func = irb_.GetRuntime(runtime_support::Get64Static);
1685 } else {
1686 runtime_func = irb_.GetRuntime(runtime_support::Get32Static);
1687 }
1688
1689 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1690
1691 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1692
1693 EmitUpdateDexPC(dex_pc);
1694
1695 static_field_value =
1696 irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
1697
1698 EmitGuard_ExceptionLandingPad(dex_pc);
1699
1700 } else {
1701 DCHECK_GE(field_offset, 0);
1702
1703 llvm::Value* static_storage_addr = NULL;
1704
1705 if (is_referrers_class) {
1706 // Fast path, static storage base is this method's class
1707 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1708
1709 static_storage_addr =
1710 irb_.LoadFromObjectOffset(method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001711 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
TDYa1275a26d442012-07-26 18:58:38 -07001712 irb_.getJObjectTy(),
1713 kTBAAConstJObject);
1714 } else {
1715 // Medium path, static storage base in a different class which
1716 // requires checks that the other class is initialized
1717 DCHECK_GE(ssb_index, 0);
1718 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1719 }
1720
1721 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1722
1723 llvm::Value* static_field_addr =
1724 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001725 irb_.getJType(field_jty)->getPointerTo());
TDYa1275a26d442012-07-26 18:58:38 -07001726
1727 // TODO: Check is_volatile. We need to generate atomic load instruction
1728 // when is_volatile is true.
1729 static_field_value = irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001730 static_field_value = SignOrZeroExtendCat1Types(static_field_value, field_jty);
TDYa1275a26d442012-07-26 18:58:38 -07001731 }
1732
1733 if (field_jty == kFloat || field_jty == kDouble) {
1734 static_field_value =
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001735 irb_.CreateBitCast(static_field_value, irb_.getJType(field_jty));
TDYa1275a26d442012-07-26 18:58:38 -07001736 }
1737
1738 return static_field_value;
1739}
1740
1741void GBCExpanderPass::Expand_HLSput(llvm::CallInst& call_inst,
1742 JType field_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001743 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1744 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1745 llvm::Value* new_value = call_inst.getArgOperand(1);
1746
1747 if (field_jty == kFloat || field_jty == kDouble) {
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001748 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty));
TDYa1275a26d442012-07-26 18:58:38 -07001749 }
1750
1751 int field_offset;
1752 int ssb_index;
1753 bool is_referrers_class;
1754 bool is_volatile;
1755
1756 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
1757 field_idx, oat_compilation_unit_, field_offset, ssb_index,
1758 is_referrers_class, is_volatile, true);
1759
1760 if (!is_fast_path) {
1761 llvm::Function* runtime_func;
1762
1763 if (field_jty == kObject) {
1764 runtime_func = irb_.GetRuntime(runtime_support::SetObjectStatic);
1765 } else if (field_jty == kLong || field_jty == kDouble) {
1766 runtime_func = irb_.GetRuntime(runtime_support::Set64Static);
1767 } else {
1768 runtime_func = irb_.GetRuntime(runtime_support::Set32Static);
1769 }
1770
1771 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1772
1773 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1774
1775 EmitUpdateDexPC(dex_pc);
1776
1777 irb_.CreateCall3(runtime_func, field_idx_value,
1778 method_object_addr, new_value);
1779
1780 EmitGuard_ExceptionLandingPad(dex_pc);
1781
1782 } else {
1783 DCHECK_GE(field_offset, 0);
1784
1785 llvm::Value* static_storage_addr = NULL;
1786
1787 if (is_referrers_class) {
1788 // Fast path, static storage base is this method's class
1789 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1790
1791 static_storage_addr =
1792 irb_.LoadFromObjectOffset(method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001793 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
TDYa1275a26d442012-07-26 18:58:38 -07001794 irb_.getJObjectTy(),
1795 kTBAAConstJObject);
1796 } else {
1797 // Medium path, static storage base in a different class which
1798 // requires checks that the other class is initialized
1799 DCHECK_GE(ssb_index, 0);
1800 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1801 }
1802
1803 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1804
1805 llvm::Value* static_field_addr =
1806 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001807 irb_.getJType(field_jty)->getPointerTo());
TDYa1275a26d442012-07-26 18:58:38 -07001808
1809 // TODO: Check is_volatile. We need to generate atomic store instruction
1810 // when is_volatile is true.
Ian Rogers76ae4fe2013-02-27 16:03:41 -08001811 new_value = TruncateCat1Types(new_value, field_jty);
TDYa1275a26d442012-07-26 18:58:38 -07001812 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
1813
1814 if (field_jty == kObject) { // If put an object, mark the GC card table.
1815 EmitMarkGCCard(new_value, static_storage_addr);
1816 }
1817 }
1818
1819 return;
1820}
1821
TDYa127f71bf5a2012-07-29 20:09:52 -07001822llvm::Value* GBCExpanderPass::Expand_ConstString(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001823 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1824 uint32_t string_idx = LV2UInt(call_inst.getArgOperand(0));
1825
1826 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
1827
TDYa127ce4cc0d2012-11-18 16:59:53 -08001828 llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
TDYa127f71bf5a2012-07-29 20:09:52 -07001829
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001830 if (!compiler_->CanAssumeStringIsPresentInDexCache(*dex_file_, string_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001831 llvm::BasicBlock* block_str_exist =
1832 CreateBasicBlockWithDexPC(dex_pc, "str_exist");
1833
1834 llvm::BasicBlock* block_str_resolve =
1835 CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
1836
1837 llvm::BasicBlock* block_cont =
1838 CreateBasicBlockWithDexPC(dex_pc, "str_cont");
1839
1840 // Test: Is the string resolved and in the dex cache?
1841 llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.getJNull());
1842
1843 irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist, kUnlikely);
1844
1845 // String is resolved, go to next basic block.
1846 irb_.SetInsertPoint(block_str_exist);
1847 irb_.CreateBr(block_cont);
1848
1849 // String is not resolved yet, resolve it now.
1850 irb_.SetInsertPoint(block_str_resolve);
1851
1852 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::ResolveString);
1853
1854 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1855
1856 llvm::Value* string_idx_value = irb_.getInt32(string_idx);
1857
1858 EmitUpdateDexPC(dex_pc);
1859
1860 llvm::Value* result = irb_.CreateCall2(runtime_func, method_object_addr,
1861 string_idx_value);
1862
1863 EmitGuard_ExceptionLandingPad(dex_pc);
1864
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001865 irb_.CreateBr(block_cont);
1866
1867
TDYa127f71bf5a2012-07-29 20:09:52 -07001868 llvm::BasicBlock* block_pre_cont = irb_.GetInsertBlock();
1869
1870 irb_.SetInsertPoint(block_cont);
1871
1872 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1873
1874 phi->addIncoming(string_addr, block_str_exist);
1875 phi->addIncoming(result, block_pre_cont);
1876
1877 string_addr = phi;
1878 }
1879
1880 return string_addr;
1881}
1882
1883llvm::Value* GBCExpanderPass::Expand_ConstClass(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001884 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1885 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1886
1887 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
1888
1889 return type_object_addr;
1890}
1891
1892void GBCExpanderPass::Expand_MonitorEnter(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001893 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1894 llvm::Value* object_addr = call_inst.getArgOperand(1);
TDYa127920be7c2012-09-10 17:13:22 -07001895 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa127f71bf5a2012-07-29 20:09:52 -07001896
TDYa127920be7c2012-09-10 17:13:22 -07001897 if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1898 EmitGuard_NullPointerException(dex_pc, object_addr);
1899 }
TDYa127f71bf5a2012-07-29 20:09:52 -07001900
TDYa127ce4cc0d2012-11-18 16:59:53 -08001901 EmitUpdateDexPC(dex_pc);
1902
TDYa127f71bf5a2012-07-29 20:09:52 -07001903 irb_.Runtime().EmitLockObject(object_addr);
1904
1905 return;
1906}
1907
1908void GBCExpanderPass::Expand_MonitorExit(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001909 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1910 llvm::Value* object_addr = call_inst.getArgOperand(1);
TDYa127920be7c2012-09-10 17:13:22 -07001911 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa127f71bf5a2012-07-29 20:09:52 -07001912
TDYa127920be7c2012-09-10 17:13:22 -07001913 if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1914 EmitGuard_NullPointerException(dex_pc, object_addr);
1915 }
TDYa127f71bf5a2012-07-29 20:09:52 -07001916
1917 EmitUpdateDexPC(dex_pc);
1918
1919 irb_.Runtime().EmitUnlockObject(object_addr);
1920
1921 EmitGuard_ExceptionLandingPad(dex_pc);
1922
1923 return;
1924}
1925
1926void GBCExpanderPass::Expand_HLCheckCast(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001927 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1928 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1929 llvm::Value* object_addr = call_inst.getArgOperand(1);
1930
1931 llvm::BasicBlock* block_test_class =
1932 CreateBasicBlockWithDexPC(dex_pc, "test_class");
1933
1934 llvm::BasicBlock* block_test_sub_class =
1935 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
1936
1937 llvm::BasicBlock* block_cont =
1938 CreateBasicBlockWithDexPC(dex_pc, "checkcast_cont");
1939
1940 // Test: Is the reference equal to null? Act as no-op when it is null.
1941 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
1942
1943 irb_.CreateCondBr(equal_null,
1944 block_cont,
1945 block_test_class);
1946
1947 // Test: Is the object instantiated from the given class?
1948 irb_.SetInsertPoint(block_test_class);
1949 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
Ian Rogers98573f92013-01-30 17:26:32 -08001950 DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
TDYa127f71bf5a2012-07-29 20:09:52 -07001951
1952 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
1953
1954 llvm::Value* object_type_field_addr =
1955 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
1956
1957 llvm::Value* object_type_object_addr =
1958 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
1959
1960 llvm::Value* equal_class =
1961 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
1962
1963 irb_.CreateCondBr(equal_class,
1964 block_cont,
1965 block_test_sub_class);
1966
1967 // Test: Is the object instantiated from the subclass of the given class?
1968 irb_.SetInsertPoint(block_test_sub_class);
1969
1970 EmitUpdateDexPC(dex_pc);
1971
1972 irb_.CreateCall2(irb_.GetRuntime(runtime_support::CheckCast),
1973 type_object_addr, object_type_object_addr);
1974
1975 EmitGuard_ExceptionLandingPad(dex_pc);
1976
1977 irb_.CreateBr(block_cont);
1978
1979 irb_.SetInsertPoint(block_cont);
1980
1981 return;
1982}
1983
1984llvm::Value* GBCExpanderPass::Expand_InstanceOf(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001985 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1986 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1987 llvm::Value* object_addr = call_inst.getArgOperand(1);
1988
1989 llvm::BasicBlock* block_nullp =
1990 CreateBasicBlockWithDexPC(dex_pc, "nullp");
1991
1992 llvm::BasicBlock* block_test_class =
1993 CreateBasicBlockWithDexPC(dex_pc, "test_class");
1994
1995 llvm::BasicBlock* block_class_equals =
1996 CreateBasicBlockWithDexPC(dex_pc, "class_eq");
1997
1998 llvm::BasicBlock* block_test_sub_class =
1999 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
2000
2001 llvm::BasicBlock* block_cont =
2002 CreateBasicBlockWithDexPC(dex_pc, "instance_of_cont");
2003
2004 // Overview of the following code :
2005 // We check for null, if so, then false, otherwise check for class == . If so
2006 // then true, otherwise do callout slowpath.
2007 //
2008 // Test: Is the reference equal to null? Set 0 when it is null.
2009 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
2010
2011 irb_.CreateCondBr(equal_null, block_nullp, block_test_class);
2012
2013 irb_.SetInsertPoint(block_nullp);
2014 irb_.CreateBr(block_cont);
2015
2016 // Test: Is the object instantiated from the given class?
2017 irb_.SetInsertPoint(block_test_class);
2018 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
Ian Rogers98573f92013-01-30 17:26:32 -08002019 DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
TDYa127f71bf5a2012-07-29 20:09:52 -07002020
2021 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
2022
2023 llvm::Value* object_type_field_addr =
2024 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
2025
2026 llvm::Value* object_type_object_addr =
2027 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
2028
2029 llvm::Value* equal_class =
2030 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
2031
2032 irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class);
2033
2034 irb_.SetInsertPoint(block_class_equals);
2035 irb_.CreateBr(block_cont);
2036
2037 // Test: Is the object instantiated from the subclass of the given class?
2038 irb_.SetInsertPoint(block_test_sub_class);
2039 llvm::Value* result =
2040 irb_.CreateCall2(irb_.GetRuntime(runtime_support::IsAssignable),
2041 type_object_addr, object_type_object_addr);
2042 irb_.CreateBr(block_cont);
2043
2044 irb_.SetInsertPoint(block_cont);
2045
2046 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJIntTy(), 3);
2047
2048 phi->addIncoming(irb_.getJInt(0), block_nullp);
2049 phi->addIncoming(irb_.getJInt(1), block_class_equals);
2050 phi->addIncoming(result, block_test_sub_class);
2051
2052 return phi;
2053}
2054
2055llvm::Value* GBCExpanderPass::Expand_NewInstance(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002056 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2057 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2058
2059 llvm::Function* runtime_func;
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002060 if (compiler_->CanAccessInstantiableTypeWithoutChecks(method_idx_, *dex_file_, type_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002061 runtime_func = irb_.GetRuntime(runtime_support::AllocObject);
2062 } else {
2063 runtime_func = irb_.GetRuntime(runtime_support::AllocObjectWithAccessCheck);
2064 }
2065
2066 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2067
2068 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2069
2070 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2071
2072 EmitUpdateDexPC(dex_pc);
2073
2074 llvm::Value* object_addr =
2075 irb_.CreateCall3(runtime_func, type_index_value, method_object_addr, thread_object_addr);
2076
2077 EmitGuard_ExceptionLandingPad(dex_pc);
2078
2079 return object_addr;
2080}
2081
2082llvm::Value* GBCExpanderPass::Expand_HLInvoke(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002083 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
TDYa127920be7c2012-09-10 17:13:22 -07002084 art::InvokeType invoke_type = static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
2085 bool is_static = (invoke_type == art::kStatic);
TDYa127f71bf5a2012-07-29 20:09:52 -07002086 uint32_t callee_method_idx = LV2UInt(call_inst.getArgOperand(1));
TDYa127920be7c2012-09-10 17:13:22 -07002087 int opt_flags = LV2UInt(call_inst.getArgOperand(2));
TDYa127f71bf5a2012-07-29 20:09:52 -07002088
2089 // Compute invoke related information for compiler decision
2090 int vtable_idx = -1;
2091 uintptr_t direct_code = 0;
2092 uintptr_t direct_method = 0;
2093 bool is_fast_path = compiler_->
2094 ComputeInvokeInfo(callee_method_idx, oat_compilation_unit_,
2095 invoke_type, vtable_idx, direct_code, direct_method);
2096
2097 // Load *this* actual parameter
2098 llvm::Value* this_addr = NULL;
2099
2100 if (!is_static) {
2101 // Test: Is *this* parameter equal to null?
2102 this_addr = call_inst.getArgOperand(3);
2103 }
2104
2105 // Load the method object
2106 llvm::Value* callee_method_object_addr = NULL;
2107
2108 if (!is_fast_path) {
2109 callee_method_object_addr =
2110 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx, invoke_type,
2111 this_addr, dex_pc, is_fast_path);
2112
TDYa127920be7c2012-09-10 17:13:22 -07002113 if (!is_static && !(opt_flags & MIR_IGNORE_NULL_CHECK)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002114 EmitGuard_NullPointerException(dex_pc, this_addr);
2115 }
2116 } else {
TDYa127920be7c2012-09-10 17:13:22 -07002117 if (!is_static && !(opt_flags & MIR_IGNORE_NULL_CHECK)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002118 EmitGuard_NullPointerException(dex_pc, this_addr);
2119 }
2120
2121 switch (invoke_type) {
TDYa127920be7c2012-09-10 17:13:22 -07002122 case art::kStatic:
2123 case art::kDirect:
TDYa127f71bf5a2012-07-29 20:09:52 -07002124 if (direct_method != 0u &&
2125 direct_method != static_cast<uintptr_t>(-1)) {
2126 callee_method_object_addr =
2127 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_method),
2128 irb_.getJObjectTy());
2129 } else {
2130 callee_method_object_addr =
2131 EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
2132 }
2133 break;
2134
TDYa127920be7c2012-09-10 17:13:22 -07002135 case art::kVirtual:
TDYa127f71bf5a2012-07-29 20:09:52 -07002136 DCHECK(vtable_idx != -1);
2137 callee_method_object_addr =
2138 EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
2139 break;
2140
TDYa127920be7c2012-09-10 17:13:22 -07002141 case art::kSuper:
TDYa127f71bf5a2012-07-29 20:09:52 -07002142 LOG(FATAL) << "invoke-super should be promoted to invoke-direct in "
2143 "the fast path.";
2144 break;
2145
TDYa127920be7c2012-09-10 17:13:22 -07002146 case art::kInterface:
TDYa127f71bf5a2012-07-29 20:09:52 -07002147 callee_method_object_addr =
2148 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx,
2149 invoke_type, this_addr,
2150 dex_pc, is_fast_path);
2151 break;
2152 }
2153 }
2154
2155 // Load the actual parameter
2156 std::vector<llvm::Value*> args;
2157
2158 args.push_back(callee_method_object_addr); // method object for callee
2159
2160 for (uint32_t i = 3; i < call_inst.getNumArgOperands(); ++i) {
2161 args.push_back(call_inst.getArgOperand(i));
2162 }
2163
2164 llvm::Value* code_addr;
2165 if (direct_code != 0u &&
2166 direct_code != static_cast<uintptr_t>(-1)) {
2167 code_addr =
2168 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_code),
2169 GetFunctionType(callee_method_idx, is_static)->getPointerTo());
2170 } else {
2171 code_addr =
2172 irb_.LoadFromObjectOffset(callee_method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08002173 art::mirror::AbstractMethod::GetCodeOffset().Int32Value(),
TDYa127f71bf5a2012-07-29 20:09:52 -07002174 GetFunctionType(callee_method_idx, is_static)->getPointerTo(),
TDYa127ce4cc0d2012-11-18 16:59:53 -08002175 kTBAARuntimeInfo);
TDYa127f71bf5a2012-07-29 20:09:52 -07002176 }
2177
2178 // Invoke callee
2179 EmitUpdateDexPC(dex_pc);
2180 llvm::Value* retval = irb_.CreateCall(code_addr, args);
2181 EmitGuard_ExceptionLandingPad(dex_pc);
2182
2183 return retval;
2184}
2185
2186llvm::Value* GBCExpanderPass::Expand_OptArrayLength(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002187 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2188 // Get the array object address
2189 llvm::Value* array_addr = call_inst.getArgOperand(1);
TDYa127920be7c2012-09-10 17:13:22 -07002190 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa127f71bf5a2012-07-29 20:09:52 -07002191
TDYa127920be7c2012-09-10 17:13:22 -07002192 if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
2193 EmitGuard_NullPointerException(dex_pc, array_addr);
2194 }
TDYa127f71bf5a2012-07-29 20:09:52 -07002195
2196 // Get the array length and store it to the register
2197 return EmitLoadArrayLength(array_addr);
2198}
2199
2200llvm::Value* GBCExpanderPass::Expand_NewArray(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002201 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2202 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2203 llvm::Value* length = call_inst.getArgOperand(1);
2204
2205 return EmitAllocNewArray(dex_pc, length, type_idx, false);
2206}
2207
2208llvm::Value* GBCExpanderPass::Expand_HLFilledNewArray(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002209 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2210 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(1));
2211 uint32_t length = call_inst.getNumArgOperands() - 3;
2212
2213 llvm::Value* object_addr =
2214 EmitAllocNewArray(dex_pc, irb_.getInt32(length), type_idx, true);
2215
2216 if (length > 0) {
2217 // Check for the element type
2218 uint32_t type_desc_len = 0;
2219 const char* type_desc =
2220 dex_file_->StringByTypeIdx(type_idx, &type_desc_len);
2221
2222 DCHECK_GE(type_desc_len, 2u); // should be guaranteed by verifier
2223 DCHECK_EQ(type_desc[0], '['); // should be guaranteed by verifier
2224 bool is_elem_int_ty = (type_desc[1] == 'I');
2225
2226 uint32_t alignment;
2227 llvm::Constant* elem_size;
2228 llvm::PointerType* field_type;
2229
2230 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
2231 // as the element, thus we are only checking 2 cases: primitive int and
2232 // non-primitive type.
2233 if (is_elem_int_ty) {
2234 alignment = sizeof(int32_t);
2235 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
2236 field_type = irb_.getJIntTy()->getPointerTo();
2237 } else {
2238 alignment = irb_.getSizeOfPtrEquivInt();
2239 elem_size = irb_.getSizeOfPtrEquivIntValue();
2240 field_type = irb_.getJObjectTy()->getPointerTo();
2241 }
2242
2243 llvm::Value* data_field_offset =
Ian Rogers98573f92013-01-30 17:26:32 -08002244 irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
TDYa127f71bf5a2012-07-29 20:09:52 -07002245
2246 llvm::Value* data_field_addr =
2247 irb_.CreatePtrDisp(object_addr, data_field_offset, field_type);
2248
2249 // TODO: Tune this code. Currently we are generating one instruction for
2250 // one element which may be very space consuming. Maybe changing to use
2251 // memcpy may help; however, since we can't guarantee that the alloca of
2252 // dalvik register are continuous, we can't perform such optimization yet.
2253 for (uint32_t i = 0; i < length; ++i) {
2254 llvm::Value* reg_value = call_inst.getArgOperand(i+3);
2255
2256 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
2257
2258 data_field_addr =
2259 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
2260 }
2261 }
2262
2263 return object_addr;
2264}
2265
2266void GBCExpanderPass::Expand_HLFillArrayData(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002267 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2268 int32_t payload_offset = static_cast<int32_t>(dex_pc) +
2269 LV2SInt(call_inst.getArgOperand(0));
2270 llvm::Value* array_addr = call_inst.getArgOperand(1);
2271
TDYa127920be7c2012-09-10 17:13:22 -07002272 const art::Instruction::ArrayDataPayload* payload =
2273 reinterpret_cast<const art::Instruction::ArrayDataPayload*>(
TDYa127f71bf5a2012-07-29 20:09:52 -07002274 code_item_->insns_ + payload_offset);
2275
2276 if (payload->element_count == 0) {
2277 // When the number of the elements in the payload is zero, we don't have
2278 // to copy any numbers. However, we should check whether the array object
2279 // address is equal to null or not.
2280 EmitGuard_NullPointerException(dex_pc, array_addr);
2281 } else {
2282 // To save the code size, we are going to call the runtime function to
2283 // copy the content from DexFile.
2284
2285 // NOTE: We will check for the NullPointerException in the runtime.
2286
2287 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::FillArrayData);
2288
2289 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2290
2291 EmitUpdateDexPC(dex_pc);
2292
2293 irb_.CreateCall4(runtime_func,
2294 method_object_addr, irb_.getInt32(dex_pc),
2295 array_addr, irb_.getInt32(payload_offset));
2296
2297 EmitGuard_ExceptionLandingPad(dex_pc);
2298 }
2299
2300 return;
2301}
2302
2303llvm::Value* GBCExpanderPass::EmitAllocNewArray(uint32_t dex_pc,
2304 llvm::Value* array_length_value,
2305 uint32_t type_idx,
2306 bool is_filled_new_array) {
2307 llvm::Function* runtime_func;
2308
2309 bool skip_access_check =
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002310 compiler_->CanAccessTypeWithoutChecks(method_idx_, *dex_file_, type_idx);
TDYa127f71bf5a2012-07-29 20:09:52 -07002311
2312
2313 if (is_filled_new_array) {
2314 runtime_func = skip_access_check ?
2315 irb_.GetRuntime(runtime_support::CheckAndAllocArray) :
2316 irb_.GetRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck);
2317 } else {
2318 runtime_func = skip_access_check ?
2319 irb_.GetRuntime(runtime_support::AllocArray) :
2320 irb_.GetRuntime(runtime_support::AllocArrayWithAccessCheck);
2321 }
2322
2323 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2324
2325 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2326
2327 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2328
2329 EmitUpdateDexPC(dex_pc);
2330
2331 llvm::Value* object_addr =
2332 irb_.CreateCall4(runtime_func, type_index_value, method_object_addr,
2333 array_length_value, thread_object_addr);
2334
2335 EmitGuard_ExceptionLandingPad(dex_pc);
2336
2337 return object_addr;
2338}
2339
2340llvm::Value* GBCExpanderPass::
2341EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
TDYa127920be7c2012-09-10 17:13:22 -07002342 art::InvokeType invoke_type,
TDYa127f71bf5a2012-07-29 20:09:52 -07002343 llvm::Value* this_addr,
2344 uint32_t dex_pc,
2345 bool is_fast_path) {
2346
2347 llvm::Function* runtime_func = NULL;
2348
2349 switch (invoke_type) {
TDYa127920be7c2012-09-10 17:13:22 -07002350 case art::kStatic:
TDYa127f71bf5a2012-07-29 20:09:52 -07002351 runtime_func = irb_.GetRuntime(runtime_support::FindStaticMethodWithAccessCheck);
2352 break;
2353
TDYa127920be7c2012-09-10 17:13:22 -07002354 case art::kDirect:
TDYa127f71bf5a2012-07-29 20:09:52 -07002355 runtime_func = irb_.GetRuntime(runtime_support::FindDirectMethodWithAccessCheck);
2356 break;
2357
TDYa127920be7c2012-09-10 17:13:22 -07002358 case art::kVirtual:
TDYa127f71bf5a2012-07-29 20:09:52 -07002359 runtime_func = irb_.GetRuntime(runtime_support::FindVirtualMethodWithAccessCheck);
2360 break;
2361
TDYa127920be7c2012-09-10 17:13:22 -07002362 case art::kSuper:
TDYa127f71bf5a2012-07-29 20:09:52 -07002363 runtime_func = irb_.GetRuntime(runtime_support::FindSuperMethodWithAccessCheck);
2364 break;
2365
TDYa127920be7c2012-09-10 17:13:22 -07002366 case art::kInterface:
TDYa127f71bf5a2012-07-29 20:09:52 -07002367 if (is_fast_path) {
2368 runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethod);
2369 } else {
2370 runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethodWithAccessCheck);
2371 }
2372 break;
2373 }
2374
2375 llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
2376
2377 if (this_addr == NULL) {
TDYa127920be7c2012-09-10 17:13:22 -07002378 DCHECK_EQ(invoke_type, art::kStatic);
TDYa127f71bf5a2012-07-29 20:09:52 -07002379 this_addr = irb_.getJNull();
2380 }
2381
2382 llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
2383
2384 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2385
2386 EmitUpdateDexPC(dex_pc);
2387
2388 llvm::Value* callee_method_object_addr =
2389 irb_.CreateCall4(runtime_func,
2390 callee_method_idx_value,
2391 this_addr,
2392 caller_method_object_addr,
2393 thread_object_addr);
2394
2395 EmitGuard_ExceptionLandingPad(dex_pc);
2396
2397 return callee_method_object_addr;
2398}
2399
TDYa1275e869b62012-07-25 00:45:39 -07002400void GBCExpanderPass::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
2401 // Using runtime support, let the target can override by InlineAssembly.
2402 irb_.Runtime().EmitMarkGCCard(value, target_addr);
2403}
2404
2405void GBCExpanderPass::EmitUpdateDexPC(uint32_t dex_pc) {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002406 if (shadow_frame_ == NULL) {
2407 return;
2408 }
TDYa1275e869b62012-07-25 00:45:39 -07002409 irb_.StoreToObjectOffset(shadow_frame_,
TDYa127920be7c2012-09-10 17:13:22 -07002410 art::ShadowFrame::DexPCOffset(),
TDYa1275e869b62012-07-25 00:45:39 -07002411 irb_.getInt32(dex_pc),
2412 kTBAAShadowFrame);
2413}
2414
2415void GBCExpanderPass::EmitGuard_DivZeroException(uint32_t dex_pc,
2416 llvm::Value* denominator,
2417 JType op_jty) {
2418 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
2419
2420 llvm::Constant* zero = irb_.getJZero(op_jty);
2421
2422 llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
2423
2424 llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
2425
2426 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
2427
2428 irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
2429
2430 irb_.SetInsertPoint(block_exception);
2431 EmitUpdateDexPC(dex_pc);
2432 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowDivZeroException));
2433 EmitBranchExceptionLandingPad(dex_pc);
2434
2435 irb_.SetInsertPoint(block_continue);
2436}
2437
2438void GBCExpanderPass::EmitGuard_NullPointerException(uint32_t dex_pc,
2439 llvm::Value* object) {
2440 llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
2441
2442 llvm::BasicBlock* block_exception =
2443 CreateBasicBlockWithDexPC(dex_pc, "nullp");
2444
2445 llvm::BasicBlock* block_continue =
2446 CreateBasicBlockWithDexPC(dex_pc, "cont");
2447
2448 irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
2449
2450 irb_.SetInsertPoint(block_exception);
2451 EmitUpdateDexPC(dex_pc);
2452 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowNullPointerException),
2453 irb_.getInt32(dex_pc));
2454 EmitBranchExceptionLandingPad(dex_pc);
2455
2456 irb_.SetInsertPoint(block_continue);
2457}
2458
2459void
2460GBCExpanderPass::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
2461 llvm::Value* array,
2462 llvm::Value* index) {
2463 llvm::Value* array_len = EmitLoadArrayLength(array);
2464
2465 llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
2466
2467 llvm::BasicBlock* block_exception =
2468 CreateBasicBlockWithDexPC(dex_pc, "overflow");
2469
2470 llvm::BasicBlock* block_continue =
2471 CreateBasicBlockWithDexPC(dex_pc, "cont");
2472
2473 irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
2474
2475 irb_.SetInsertPoint(block_exception);
2476
2477 EmitUpdateDexPC(dex_pc);
2478 irb_.CreateCall2(irb_.GetRuntime(runtime_support::ThrowIndexOutOfBounds), index, array_len);
2479 EmitBranchExceptionLandingPad(dex_pc);
2480
2481 irb_.SetInsertPoint(block_continue);
2482}
2483
TDYa1275e869b62012-07-25 00:45:39 -07002484llvm::FunctionType* GBCExpanderPass::GetFunctionType(uint32_t method_idx,
2485 bool is_static) {
2486 // Get method signature
TDYa127920be7c2012-09-10 17:13:22 -07002487 art::DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
TDYa1275e869b62012-07-25 00:45:39 -07002488
2489 uint32_t shorty_size;
2490 const char* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
2491 CHECK_GE(shorty_size, 1u);
2492
2493 // Get return type
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002494
2495 char ret_shorty = shorty[0];
buzbee26f10ee2012-12-21 11:16:29 -08002496 ret_shorty = art::RemapShorty(ret_shorty);
Ian Rogers76ae4fe2013-02-27 16:03:41 -08002497 llvm::Type* ret_type = irb_.getJType(ret_shorty);
TDYa1275e869b62012-07-25 00:45:39 -07002498
2499 // Get argument type
2500 std::vector<llvm::Type*> args_type;
2501
2502 args_type.push_back(irb_.getJObjectTy()); // method object pointer
2503
2504 if (!is_static) {
Ian Rogers76ae4fe2013-02-27 16:03:41 -08002505 args_type.push_back(irb_.getJType('L')); // "this" object pointer
TDYa1275e869b62012-07-25 00:45:39 -07002506 }
2507
2508 for (uint32_t i = 1; i < shorty_size; ++i) {
buzbee26f10ee2012-12-21 11:16:29 -08002509 char shorty_type = art::RemapShorty(shorty[i]);
Ian Rogers76ae4fe2013-02-27 16:03:41 -08002510 args_type.push_back(irb_.getJType(shorty_type));
TDYa1275e869b62012-07-25 00:45:39 -07002511 }
2512
2513 return llvm::FunctionType::get(ret_type, args_type, false);
2514}
2515
2516
2517llvm::BasicBlock* GBCExpanderPass::
2518CreateBasicBlockWithDexPC(uint32_t dex_pc, const char* postfix) {
2519 std::string name;
2520
2521#if !defined(NDEBUG)
TDYa127920be7c2012-09-10 17:13:22 -07002522 art::StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
TDYa1275e869b62012-07-25 00:45:39 -07002523#endif
2524
2525 return llvm::BasicBlock::Create(context_, name, func_);
2526}
2527
2528llvm::BasicBlock* GBCExpanderPass::GetBasicBlock(uint32_t dex_pc) {
2529 DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002530 CHECK(basic_blocks_[dex_pc] != NULL);
TDYa1275e869b62012-07-25 00:45:39 -07002531 return basic_blocks_[dex_pc];
2532}
2533
2534int32_t GBCExpanderPass::GetTryItemOffset(uint32_t dex_pc) {
2535 int32_t min = 0;
2536 int32_t max = code_item_->tries_size_ - 1;
2537
2538 while (min <= max) {
2539 int32_t mid = min + (max - min) / 2;
2540
TDYa127920be7c2012-09-10 17:13:22 -07002541 const art::DexFile::TryItem* ti = art::DexFile::GetTryItems(*code_item_, mid);
TDYa1275e869b62012-07-25 00:45:39 -07002542 uint32_t start = ti->start_addr_;
2543 uint32_t end = start + ti->insn_count_;
2544
2545 if (dex_pc < start) {
2546 max = mid - 1;
2547 } else if (dex_pc >= end) {
2548 min = mid + 1;
2549 } else {
2550 return mid; // found
2551 }
2552 }
2553
2554 return -1; // not found
2555}
2556
2557llvm::BasicBlock* GBCExpanderPass::GetLandingPadBasicBlock(uint32_t dex_pc) {
2558 // Find the try item for this address in this method
2559 int32_t ti_offset = GetTryItemOffset(dex_pc);
2560
2561 if (ti_offset == -1) {
2562 return NULL; // No landing pad is available for this address.
2563 }
2564
2565 // Check for the existing landing pad basic block
2566 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2567 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
2568
2569 if (block_lpad) {
2570 // We have generated landing pad for this try item already. Return the
2571 // same basic block.
2572 return block_lpad;
2573 }
2574
2575 // Get try item from code item
TDYa127920be7c2012-09-10 17:13:22 -07002576 const art::DexFile::TryItem* ti = art::DexFile::GetTryItems(*code_item_, ti_offset);
TDYa1275e869b62012-07-25 00:45:39 -07002577
2578 std::string lpadname;
2579
2580#if !defined(NDEBUG)
TDYa127920be7c2012-09-10 17:13:22 -07002581 art::StringAppendF(&lpadname, "lpad%d_%04x_to_%04x", ti_offset, ti->start_addr_, ti->handler_off_);
TDYa1275e869b62012-07-25 00:45:39 -07002582#endif
2583
2584 // Create landing pad basic block
2585 block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
2586
2587 // Change IRBuilder insert point
2588 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2589 irb_.SetInsertPoint(block_lpad);
2590
2591 // Find catch block with matching type
2592 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2593
2594 llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
2595
2596 llvm::Value* catch_handler_index_value =
2597 irb_.CreateCall2(irb_.GetRuntime(runtime_support::FindCatchBlock),
2598 method_object_addr, ti_offset_value);
2599
2600 // Switch instruction (Go to unwind basic block by default)
2601 llvm::SwitchInst* sw =
2602 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
2603
2604 // Cases with matched catch block
TDYa127920be7c2012-09-10 17:13:22 -07002605 art::CatchHandlerIterator iter(*code_item_, ti->start_addr_);
TDYa1275e869b62012-07-25 00:45:39 -07002606
2607 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
2608 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
2609 }
2610
2611 // Restore the orignal insert point for IRBuilder
2612 irb_.restoreIP(irb_ip_original);
2613
2614 // Cache this landing pad
2615 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2616 basic_block_landing_pads_[ti_offset] = block_lpad;
2617
2618 return block_lpad;
2619}
2620
2621llvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() {
2622 // Check the existing unwinding baisc block block
2623 if (basic_block_unwind_ != NULL) {
2624 return basic_block_unwind_;
2625 }
2626
2627 // Create new basic block for unwinding
2628 basic_block_unwind_ =
2629 llvm::BasicBlock::Create(context_, "exception_unwind", func_);
2630
2631 // Change IRBuilder insert point
2632 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2633 irb_.SetInsertPoint(basic_block_unwind_);
2634
2635 // Pop the shadow frame
2636 Expand_PopShadowFrame();
2637
2638 // Emit the code to return default value (zero) for the given return type.
2639 char ret_shorty = oat_compilation_unit_->GetShorty()[0];
buzbee26f10ee2012-12-21 11:16:29 -08002640 ret_shorty = art::RemapShorty(ret_shorty);
TDYa1275e869b62012-07-25 00:45:39 -07002641 if (ret_shorty == 'V') {
2642 irb_.CreateRetVoid();
2643 } else {
2644 irb_.CreateRet(irb_.getJZero(ret_shorty));
2645 }
2646
2647 // Restore the orignal insert point for IRBuilder
2648 irb_.restoreIP(irb_ip_original);
2649
2650 return basic_block_unwind_;
2651}
2652
2653void GBCExpanderPass::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
2654 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
TDYa12755e5e6c2012-09-11 15:14:42 -07002655 landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
TDYa127aa558872012-08-16 05:11:07 -07002656 irb_.GetInsertBlock()));
TDYa1275e869b62012-07-25 00:45:39 -07002657 irb_.CreateBr(lpad);
2658 } else {
2659 irb_.CreateBr(GetUnwindBasicBlock());
2660 }
2661}
2662
2663void GBCExpanderPass::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
Jeff Hao9a142652013-01-17 23:10:19 +00002664 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
2665
TDYa1275e869b62012-07-25 00:45:39 -07002666 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
2667
2668 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
TDYa12755e5e6c2012-09-11 15:14:42 -07002669 landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
TDYa127aa558872012-08-16 05:11:07 -07002670 irb_.GetInsertBlock()));
Jeff Hao9a142652013-01-17 23:10:19 +00002671 irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
TDYa1275e869b62012-07-25 00:45:39 -07002672 } else {
Jeff Hao9a142652013-01-17 23:10:19 +00002673 irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
TDYa1275e869b62012-07-25 00:45:39 -07002674 }
2675
2676 irb_.SetInsertPoint(block_cont);
2677}
2678
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002679llvm::Value*
2680GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
2681 llvm::CallInst& call_inst) {
2682 switch (intr_id) {
2683 //==- Thread -----------------------------------------------------------==//
2684 case IntrinsicHelper::GetCurrentThread: {
TDYa127b672d1e2012-06-28 21:21:45 -07002685 return irb_.Runtime().EmitGetCurrentThread();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002686 }
Logan Chien75e4b602012-07-23 14:24:12 -07002687 case IntrinsicHelper::CheckSuspend: {
TDYa127ce4cc0d2012-11-18 16:59:53 -08002688 Expand_TestSuspend(call_inst);
TDYa127890ea892012-08-22 10:49:42 -07002689 return NULL;
2690 }
2691 case IntrinsicHelper::TestSuspend: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002692 Expand_TestSuspend(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002693 return NULL;
2694 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002695 case IntrinsicHelper::MarkGCCard: {
TDYa1279a129452012-07-19 03:10:08 -07002696 Expand_MarkGCCard(call_inst);
2697 return NULL;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002698 }
Logan Chien75e4b602012-07-23 14:24:12 -07002699
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002700 //==- Exception --------------------------------------------------------==//
2701 case IntrinsicHelper::ThrowException: {
2702 return ExpandToRuntime(runtime_support::ThrowException, call_inst);
2703 }
TDYa127f71bf5a2012-07-29 20:09:52 -07002704 case IntrinsicHelper::HLThrowException: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002705 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2706
2707 EmitUpdateDexPC(dex_pc);
2708
2709 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowException),
2710 call_inst.getArgOperand(0));
2711
2712 EmitGuard_ExceptionLandingPad(dex_pc);
2713 return NULL;
2714 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002715 case IntrinsicHelper::GetException: {
TDYa127823433d2012-09-26 16:03:51 -07002716 return irb_.Runtime().EmitGetAndClearException();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002717 }
2718 case IntrinsicHelper::IsExceptionPending: {
2719 return irb_.Runtime().EmitIsExceptionPending();
2720 }
2721 case IntrinsicHelper::FindCatchBlock: {
2722 return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
2723 }
2724 case IntrinsicHelper::ThrowDivZeroException: {
2725 return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
2726 }
2727 case IntrinsicHelper::ThrowNullPointerException: {
2728 return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
2729 }
2730 case IntrinsicHelper::ThrowIndexOutOfBounds: {
2731 return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
2732 }
Logan Chien75e4b602012-07-23 14:24:12 -07002733
2734 //==- Const String -----------------------------------------------------==//
2735 case IntrinsicHelper::ConstString: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002736 return Expand_ConstString(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002737 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002738 case IntrinsicHelper::LoadStringFromDexCache: {
2739 return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
2740 }
2741 case IntrinsicHelper::ResolveString: {
2742 return ExpandToRuntime(runtime_support::ResolveString, call_inst);
2743 }
Logan Chien75e4b602012-07-23 14:24:12 -07002744
2745 //==- Const Class ------------------------------------------------------==//
2746 case IntrinsicHelper::ConstClass: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002747 return Expand_ConstClass(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002748 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002749 case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
2750 return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
2751 }
2752 case IntrinsicHelper::LoadTypeFromDexCache: {
2753 return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
2754 }
2755 case IntrinsicHelper::InitializeType: {
2756 return ExpandToRuntime(runtime_support::InitializeType, call_inst);
2757 }
Logan Chien75e4b602012-07-23 14:24:12 -07002758
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002759 //==- Lock -------------------------------------------------------------==//
2760 case IntrinsicHelper::LockObject: {
2761 Expand_LockObject(call_inst.getArgOperand(0));
2762 return NULL;
2763 }
2764 case IntrinsicHelper::UnlockObject: {
2765 Expand_UnlockObject(call_inst.getArgOperand(0));
2766 return NULL;
2767 }
Logan Chien75e4b602012-07-23 14:24:12 -07002768
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002769 //==- Cast -------------------------------------------------------------==//
2770 case IntrinsicHelper::CheckCast: {
2771 return ExpandToRuntime(runtime_support::CheckCast, call_inst);
2772 }
Logan Chien75e4b602012-07-23 14:24:12 -07002773 case IntrinsicHelper::HLCheckCast: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002774 Expand_HLCheckCast(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002775 return NULL;
2776 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002777 case IntrinsicHelper::IsAssignable: {
2778 return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
2779 }
Logan Chien75e4b602012-07-23 14:24:12 -07002780
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002781 //==- Alloc ------------------------------------------------------------==//
2782 case IntrinsicHelper::AllocObject: {
2783 return ExpandToRuntime(runtime_support::AllocObject, call_inst);
2784 }
2785 case IntrinsicHelper::AllocObjectWithAccessCheck: {
2786 return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
2787 }
Logan Chien75e4b602012-07-23 14:24:12 -07002788
2789 //==- Instance ---------------------------------------------------------==//
2790 case IntrinsicHelper::NewInstance: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002791 return Expand_NewInstance(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002792 }
2793 case IntrinsicHelper::InstanceOf: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002794 return Expand_InstanceOf(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002795 }
2796
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002797 //==- Array ------------------------------------------------------------==//
Logan Chien75e4b602012-07-23 14:24:12 -07002798 case IntrinsicHelper::NewArray: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002799 return Expand_NewArray(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002800 }
2801 case IntrinsicHelper::OptArrayLength: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002802 return Expand_OptArrayLength(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002803 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002804 case IntrinsicHelper::ArrayLength: {
2805 return EmitLoadArrayLength(call_inst.getArgOperand(0));
2806 }
2807 case IntrinsicHelper::AllocArray: {
2808 return ExpandToRuntime(runtime_support::AllocArray, call_inst);
2809 }
2810 case IntrinsicHelper::AllocArrayWithAccessCheck: {
2811 return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
2812 call_inst);
2813 }
2814 case IntrinsicHelper::CheckAndAllocArray: {
2815 return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
2816 }
2817 case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
2818 return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
2819 call_inst);
2820 }
2821 case IntrinsicHelper::ArrayGet: {
2822 return Expand_ArrayGet(call_inst.getArgOperand(0),
2823 call_inst.getArgOperand(1),
2824 kInt);
2825 }
2826 case IntrinsicHelper::ArrayGetWide: {
2827 return Expand_ArrayGet(call_inst.getArgOperand(0),
2828 call_inst.getArgOperand(1),
2829 kLong);
2830 }
2831 case IntrinsicHelper::ArrayGetObject: {
2832 return Expand_ArrayGet(call_inst.getArgOperand(0),
2833 call_inst.getArgOperand(1),
2834 kObject);
2835 }
2836 case IntrinsicHelper::ArrayGetBoolean: {
2837 return Expand_ArrayGet(call_inst.getArgOperand(0),
2838 call_inst.getArgOperand(1),
2839 kBoolean);
2840 }
2841 case IntrinsicHelper::ArrayGetByte: {
2842 return Expand_ArrayGet(call_inst.getArgOperand(0),
2843 call_inst.getArgOperand(1),
2844 kByte);
2845 }
2846 case IntrinsicHelper::ArrayGetChar: {
2847 return Expand_ArrayGet(call_inst.getArgOperand(0),
2848 call_inst.getArgOperand(1),
2849 kChar);
2850 }
2851 case IntrinsicHelper::ArrayGetShort: {
2852 return Expand_ArrayGet(call_inst.getArgOperand(0),
2853 call_inst.getArgOperand(1),
2854 kShort);
2855 }
2856 case IntrinsicHelper::ArrayPut: {
2857 Expand_ArrayPut(call_inst.getArgOperand(0),
2858 call_inst.getArgOperand(1),
2859 call_inst.getArgOperand(2),
2860 kInt);
2861 return NULL;
2862 }
2863 case IntrinsicHelper::ArrayPutWide: {
2864 Expand_ArrayPut(call_inst.getArgOperand(0),
2865 call_inst.getArgOperand(1),
2866 call_inst.getArgOperand(2),
2867 kLong);
2868 return NULL;
2869 }
2870 case IntrinsicHelper::ArrayPutObject: {
2871 Expand_ArrayPut(call_inst.getArgOperand(0),
2872 call_inst.getArgOperand(1),
2873 call_inst.getArgOperand(2),
2874 kObject);
2875 return NULL;
2876 }
2877 case IntrinsicHelper::ArrayPutBoolean: {
2878 Expand_ArrayPut(call_inst.getArgOperand(0),
2879 call_inst.getArgOperand(1),
2880 call_inst.getArgOperand(2),
2881 kBoolean);
2882 return NULL;
2883 }
2884 case IntrinsicHelper::ArrayPutByte: {
2885 Expand_ArrayPut(call_inst.getArgOperand(0),
2886 call_inst.getArgOperand(1),
2887 call_inst.getArgOperand(2),
2888 kByte);
2889 return NULL;
2890 }
2891 case IntrinsicHelper::ArrayPutChar: {
2892 Expand_ArrayPut(call_inst.getArgOperand(0),
2893 call_inst.getArgOperand(1),
2894 call_inst.getArgOperand(2),
2895 kChar);
2896 return NULL;
2897 }
2898 case IntrinsicHelper::ArrayPutShort: {
2899 Expand_ArrayPut(call_inst.getArgOperand(0),
2900 call_inst.getArgOperand(1),
2901 call_inst.getArgOperand(2),
2902 kShort);
2903 return NULL;
2904 }
2905 case IntrinsicHelper::CheckPutArrayElement: {
2906 return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
2907 }
2908 case IntrinsicHelper::FilledNewArray: {
2909 Expand_FilledNewArray(call_inst);
2910 return NULL;
2911 }
2912 case IntrinsicHelper::FillArrayData: {
2913 return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
2914 }
Logan Chien75e4b602012-07-23 14:24:12 -07002915 case IntrinsicHelper::HLFillArrayData: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002916 Expand_HLFillArrayData(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002917 return NULL;
2918 }
2919 case IntrinsicHelper::HLFilledNewArray: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002920 return Expand_HLFilledNewArray(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002921 }
2922
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002923 //==- Instance Field ---------------------------------------------------==//
2924 case IntrinsicHelper::InstanceFieldGet:
2925 case IntrinsicHelper::InstanceFieldGetBoolean:
2926 case IntrinsicHelper::InstanceFieldGetByte:
2927 case IntrinsicHelper::InstanceFieldGetChar:
2928 case IntrinsicHelper::InstanceFieldGetShort: {
2929 return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
2930 }
2931 case IntrinsicHelper::InstanceFieldGetWide: {
2932 return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
2933 }
2934 case IntrinsicHelper::InstanceFieldGetObject: {
2935 return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
2936 }
2937 case IntrinsicHelper::InstanceFieldGetFast: {
2938 return Expand_IGetFast(call_inst.getArgOperand(0),
2939 call_inst.getArgOperand(1),
2940 call_inst.getArgOperand(2),
2941 kInt);
2942 }
2943 case IntrinsicHelper::InstanceFieldGetWideFast: {
2944 return Expand_IGetFast(call_inst.getArgOperand(0),
2945 call_inst.getArgOperand(1),
2946 call_inst.getArgOperand(2),
2947 kLong);
2948 }
2949 case IntrinsicHelper::InstanceFieldGetObjectFast: {
2950 return Expand_IGetFast(call_inst.getArgOperand(0),
2951 call_inst.getArgOperand(1),
2952 call_inst.getArgOperand(2),
2953 kObject);
2954 }
2955 case IntrinsicHelper::InstanceFieldGetBooleanFast: {
2956 return Expand_IGetFast(call_inst.getArgOperand(0),
2957 call_inst.getArgOperand(1),
2958 call_inst.getArgOperand(2),
2959 kBoolean);
2960 }
2961 case IntrinsicHelper::InstanceFieldGetByteFast: {
2962 return Expand_IGetFast(call_inst.getArgOperand(0),
2963 call_inst.getArgOperand(1),
2964 call_inst.getArgOperand(2),
2965 kByte);
2966 }
2967 case IntrinsicHelper::InstanceFieldGetCharFast: {
2968 return Expand_IGetFast(call_inst.getArgOperand(0),
2969 call_inst.getArgOperand(1),
2970 call_inst.getArgOperand(2),
2971 kChar);
2972 }
2973 case IntrinsicHelper::InstanceFieldGetShortFast: {
2974 return Expand_IGetFast(call_inst.getArgOperand(0),
2975 call_inst.getArgOperand(1),
2976 call_inst.getArgOperand(2),
2977 kShort);
2978 }
2979 case IntrinsicHelper::InstanceFieldPut:
2980 case IntrinsicHelper::InstanceFieldPutBoolean:
2981 case IntrinsicHelper::InstanceFieldPutByte:
2982 case IntrinsicHelper::InstanceFieldPutChar:
2983 case IntrinsicHelper::InstanceFieldPutShort: {
2984 return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
2985 }
2986 case IntrinsicHelper::InstanceFieldPutWide: {
2987 return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
2988 }
2989 case IntrinsicHelper::InstanceFieldPutObject: {
2990 return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
2991 }
2992 case IntrinsicHelper::InstanceFieldPutFast: {
2993 Expand_IPutFast(call_inst.getArgOperand(0),
2994 call_inst.getArgOperand(1),
2995 call_inst.getArgOperand(2),
2996 call_inst.getArgOperand(3),
2997 kInt);
2998 return NULL;
2999 }
3000 case IntrinsicHelper::InstanceFieldPutWideFast: {
3001 Expand_IPutFast(call_inst.getArgOperand(0),
3002 call_inst.getArgOperand(1),
3003 call_inst.getArgOperand(2),
3004 call_inst.getArgOperand(3),
3005 kLong);
3006 return NULL;
3007 }
3008 case IntrinsicHelper::InstanceFieldPutObjectFast: {
3009 Expand_IPutFast(call_inst.getArgOperand(0),
3010 call_inst.getArgOperand(1),
3011 call_inst.getArgOperand(2),
3012 call_inst.getArgOperand(3),
3013 kObject);
3014 return NULL;
3015 }
3016 case IntrinsicHelper::InstanceFieldPutBooleanFast: {
3017 Expand_IPutFast(call_inst.getArgOperand(0),
3018 call_inst.getArgOperand(1),
3019 call_inst.getArgOperand(2),
3020 call_inst.getArgOperand(3),
3021 kBoolean);
3022 return NULL;
3023 }
3024 case IntrinsicHelper::InstanceFieldPutByteFast: {
3025 Expand_IPutFast(call_inst.getArgOperand(0),
3026 call_inst.getArgOperand(1),
3027 call_inst.getArgOperand(2),
3028 call_inst.getArgOperand(3),
3029 kByte);
3030 return NULL;
3031 }
3032 case IntrinsicHelper::InstanceFieldPutCharFast: {
3033 Expand_IPutFast(call_inst.getArgOperand(0),
3034 call_inst.getArgOperand(1),
3035 call_inst.getArgOperand(2),
3036 call_inst.getArgOperand(3),
3037 kChar);
3038 return NULL;
3039 }
3040 case IntrinsicHelper::InstanceFieldPutShortFast: {
3041 Expand_IPutFast(call_inst.getArgOperand(0),
3042 call_inst.getArgOperand(1),
3043 call_inst.getArgOperand(2),
3044 call_inst.getArgOperand(3),
3045 kShort);
3046 return NULL;
3047 }
Logan Chien75e4b602012-07-23 14:24:12 -07003048
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003049 //==- Static Field -----------------------------------------------------==//
3050 case IntrinsicHelper::StaticFieldGet:
3051 case IntrinsicHelper::StaticFieldGetBoolean:
3052 case IntrinsicHelper::StaticFieldGetByte:
3053 case IntrinsicHelper::StaticFieldGetChar:
3054 case IntrinsicHelper::StaticFieldGetShort: {
3055 return ExpandToRuntime(runtime_support::Get32Static, call_inst);
3056 }
3057 case IntrinsicHelper::StaticFieldGetWide: {
3058 return ExpandToRuntime(runtime_support::Get64Static, call_inst);
3059 }
3060 case IntrinsicHelper::StaticFieldGetObject: {
3061 return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
3062 }
3063 case IntrinsicHelper::StaticFieldGetFast: {
3064 return Expand_SGetFast(call_inst.getArgOperand(0),
3065 call_inst.getArgOperand(1),
3066 call_inst.getArgOperand(2),
3067 kInt);
3068 }
3069 case IntrinsicHelper::StaticFieldGetWideFast: {
3070 return Expand_SGetFast(call_inst.getArgOperand(0),
3071 call_inst.getArgOperand(1),
3072 call_inst.getArgOperand(2),
3073 kLong);
3074 }
3075 case IntrinsicHelper::StaticFieldGetObjectFast: {
3076 return Expand_SGetFast(call_inst.getArgOperand(0),
3077 call_inst.getArgOperand(1),
3078 call_inst.getArgOperand(2),
3079 kObject);
3080 }
3081 case IntrinsicHelper::StaticFieldGetBooleanFast: {
3082 return Expand_SGetFast(call_inst.getArgOperand(0),
3083 call_inst.getArgOperand(1),
3084 call_inst.getArgOperand(2),
3085 kBoolean);
3086 }
3087 case IntrinsicHelper::StaticFieldGetByteFast: {
3088 return Expand_SGetFast(call_inst.getArgOperand(0),
3089 call_inst.getArgOperand(1),
3090 call_inst.getArgOperand(2),
3091 kByte);
3092 }
3093 case IntrinsicHelper::StaticFieldGetCharFast: {
3094 return Expand_SGetFast(call_inst.getArgOperand(0),
3095 call_inst.getArgOperand(1),
3096 call_inst.getArgOperand(2),
3097 kChar);
3098 }
3099 case IntrinsicHelper::StaticFieldGetShortFast: {
3100 return Expand_SGetFast(call_inst.getArgOperand(0),
3101 call_inst.getArgOperand(1),
3102 call_inst.getArgOperand(2),
3103 kShort);
3104 }
3105 case IntrinsicHelper::StaticFieldPut:
3106 case IntrinsicHelper::StaticFieldPutBoolean:
3107 case IntrinsicHelper::StaticFieldPutByte:
3108 case IntrinsicHelper::StaticFieldPutChar:
3109 case IntrinsicHelper::StaticFieldPutShort: {
3110 return ExpandToRuntime(runtime_support::Set32Static, call_inst);
3111 }
3112 case IntrinsicHelper::StaticFieldPutWide: {
3113 return ExpandToRuntime(runtime_support::Set64Static, call_inst);
3114 }
3115 case IntrinsicHelper::StaticFieldPutObject: {
3116 return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
3117 }
3118 case IntrinsicHelper::StaticFieldPutFast: {
3119 Expand_SPutFast(call_inst.getArgOperand(0),
3120 call_inst.getArgOperand(1),
3121 call_inst.getArgOperand(2),
3122 call_inst.getArgOperand(3),
3123 kInt);
3124 return NULL;
3125 }
3126 case IntrinsicHelper::StaticFieldPutWideFast: {
3127 Expand_SPutFast(call_inst.getArgOperand(0),
3128 call_inst.getArgOperand(1),
3129 call_inst.getArgOperand(2),
3130 call_inst.getArgOperand(3),
3131 kLong);
3132 return NULL;
3133 }
3134 case IntrinsicHelper::StaticFieldPutObjectFast: {
3135 Expand_SPutFast(call_inst.getArgOperand(0),
3136 call_inst.getArgOperand(1),
3137 call_inst.getArgOperand(2),
3138 call_inst.getArgOperand(3),
3139 kObject);
3140 return NULL;
3141 }
3142 case IntrinsicHelper::StaticFieldPutBooleanFast: {
3143 Expand_SPutFast(call_inst.getArgOperand(0),
3144 call_inst.getArgOperand(1),
3145 call_inst.getArgOperand(2),
3146 call_inst.getArgOperand(3),
3147 kBoolean);
3148 return NULL;
3149 }
3150 case IntrinsicHelper::StaticFieldPutByteFast: {
3151 Expand_SPutFast(call_inst.getArgOperand(0),
3152 call_inst.getArgOperand(1),
3153 call_inst.getArgOperand(2),
3154 call_inst.getArgOperand(3),
3155 kByte);
3156 return NULL;
3157 }
3158 case IntrinsicHelper::StaticFieldPutCharFast: {
3159 Expand_SPutFast(call_inst.getArgOperand(0),
3160 call_inst.getArgOperand(1),
3161 call_inst.getArgOperand(2),
3162 call_inst.getArgOperand(3),
3163 kChar);
3164 return NULL;
3165 }
3166 case IntrinsicHelper::StaticFieldPutShortFast: {
3167 Expand_SPutFast(call_inst.getArgOperand(0),
3168 call_inst.getArgOperand(1),
3169 call_inst.getArgOperand(2),
3170 call_inst.getArgOperand(3),
3171 kShort);
3172 return NULL;
3173 }
3174 case IntrinsicHelper::LoadDeclaringClassSSB: {
3175 return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
3176 }
3177 case IntrinsicHelper::LoadClassSSBFromDexCache: {
3178 return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
3179 }
3180 case IntrinsicHelper::InitializeAndLoadClassSSB: {
3181 return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
3182 }
Logan Chien75e4b602012-07-23 14:24:12 -07003183
3184 //==- High-level Array -------------------------------------------------==//
3185 case IntrinsicHelper::HLArrayGet: {
TDYa1275a26d442012-07-26 18:58:38 -07003186 return Expand_HLArrayGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003187 }
3188 case IntrinsicHelper::HLArrayGetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003189 return Expand_HLArrayGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003190 }
3191 case IntrinsicHelper::HLArrayGetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003192 return Expand_HLArrayGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003193 }
3194 case IntrinsicHelper::HLArrayGetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003195 return Expand_HLArrayGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003196 }
3197 case IntrinsicHelper::HLArrayGetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003198 return Expand_HLArrayGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003199 }
3200 case IntrinsicHelper::HLArrayGetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003201 return Expand_HLArrayGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003202 }
3203 case IntrinsicHelper::HLArrayGetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003204 return Expand_HLArrayGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003205 }
3206 case IntrinsicHelper::HLArrayGetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003207 return Expand_HLArrayGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003208 }
3209 case IntrinsicHelper::HLArrayGetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003210 return Expand_HLArrayGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003211 }
3212 case IntrinsicHelper::HLArrayPut: {
TDYa1275a26d442012-07-26 18:58:38 -07003213 Expand_HLArrayPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003214 return NULL;
3215 }
3216 case IntrinsicHelper::HLArrayPutBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003217 Expand_HLArrayPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003218 return NULL;
3219 }
3220 case IntrinsicHelper::HLArrayPutByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003221 Expand_HLArrayPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003222 return NULL;
3223 }
3224 case IntrinsicHelper::HLArrayPutChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003225 Expand_HLArrayPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003226 return NULL;
3227 }
3228 case IntrinsicHelper::HLArrayPutShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003229 Expand_HLArrayPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003230 return NULL;
3231 }
3232 case IntrinsicHelper::HLArrayPutFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003233 Expand_HLArrayPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003234 return NULL;
3235 }
3236 case IntrinsicHelper::HLArrayPutWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003237 Expand_HLArrayPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003238 return NULL;
3239 }
3240 case IntrinsicHelper::HLArrayPutDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003241 Expand_HLArrayPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003242 return NULL;
3243 }
3244 case IntrinsicHelper::HLArrayPutObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003245 Expand_HLArrayPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003246 return NULL;
3247 }
3248
3249 //==- High-level Instance ----------------------------------------------==//
3250 case IntrinsicHelper::HLIGet: {
TDYa1275e869b62012-07-25 00:45:39 -07003251 return Expand_HLIGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003252 }
3253 case IntrinsicHelper::HLIGetBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07003254 return Expand_HLIGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003255 }
3256 case IntrinsicHelper::HLIGetByte: {
TDYa1275e869b62012-07-25 00:45:39 -07003257 return Expand_HLIGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003258 }
3259 case IntrinsicHelper::HLIGetChar: {
TDYa1275e869b62012-07-25 00:45:39 -07003260 return Expand_HLIGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003261 }
3262 case IntrinsicHelper::HLIGetShort: {
TDYa1275e869b62012-07-25 00:45:39 -07003263 return Expand_HLIGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003264 }
3265 case IntrinsicHelper::HLIGetFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07003266 return Expand_HLIGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003267 }
3268 case IntrinsicHelper::HLIGetWide: {
TDYa1275e869b62012-07-25 00:45:39 -07003269 return Expand_HLIGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003270 }
3271 case IntrinsicHelper::HLIGetDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07003272 return Expand_HLIGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003273 }
3274 case IntrinsicHelper::HLIGetObject: {
TDYa1275e869b62012-07-25 00:45:39 -07003275 return Expand_HLIGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003276 }
3277 case IntrinsicHelper::HLIPut: {
TDYa1275e869b62012-07-25 00:45:39 -07003278 Expand_HLIPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003279 return NULL;
3280 }
3281 case IntrinsicHelper::HLIPutBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07003282 Expand_HLIPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003283 return NULL;
3284 }
3285 case IntrinsicHelper::HLIPutByte: {
TDYa1275e869b62012-07-25 00:45:39 -07003286 Expand_HLIPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003287 return NULL;
3288 }
3289 case IntrinsicHelper::HLIPutChar: {
TDYa1275e869b62012-07-25 00:45:39 -07003290 Expand_HLIPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003291 return NULL;
3292 }
3293 case IntrinsicHelper::HLIPutShort: {
TDYa1275e869b62012-07-25 00:45:39 -07003294 Expand_HLIPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003295 return NULL;
3296 }
3297 case IntrinsicHelper::HLIPutFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07003298 Expand_HLIPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003299 return NULL;
3300 }
3301 case IntrinsicHelper::HLIPutWide: {
TDYa1275e869b62012-07-25 00:45:39 -07003302 Expand_HLIPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003303 return NULL;
3304 }
3305 case IntrinsicHelper::HLIPutDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07003306 Expand_HLIPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003307 return NULL;
3308 }
3309 case IntrinsicHelper::HLIPutObject: {
TDYa1275e869b62012-07-25 00:45:39 -07003310 Expand_HLIPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003311 return NULL;
3312 }
3313
3314 //==- High-level Invoke ------------------------------------------------==//
TDYa127f71bf5a2012-07-29 20:09:52 -07003315 case IntrinsicHelper::HLInvokeVoid:
3316 case IntrinsicHelper::HLInvokeObj:
3317 case IntrinsicHelper::HLInvokeInt:
3318 case IntrinsicHelper::HLInvokeFloat:
3319 case IntrinsicHelper::HLInvokeLong:
Logan Chien75e4b602012-07-23 14:24:12 -07003320 case IntrinsicHelper::HLInvokeDouble: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003321 return Expand_HLInvoke(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003322 }
3323
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003324 //==- Invoke -----------------------------------------------------------==//
3325 case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
3326 return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
3327 }
3328 case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
3329 return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
3330 }
3331 case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
3332 return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
3333 }
3334 case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
3335 return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
3336 }
3337 case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
3338 return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
3339 }
3340 case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
3341 return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
3342 }
3343 case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
3344 return Expand_GetVirtualCalleeMethodObjAddrFast(
3345 call_inst.getArgOperand(0), call_inst.getArgOperand(1));
3346 }
3347 case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
3348 return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
3349 }
3350 case IntrinsicHelper::InvokeRetVoid:
3351 case IntrinsicHelper::InvokeRetBoolean:
3352 case IntrinsicHelper::InvokeRetByte:
3353 case IntrinsicHelper::InvokeRetChar:
3354 case IntrinsicHelper::InvokeRetShort:
3355 case IntrinsicHelper::InvokeRetInt:
3356 case IntrinsicHelper::InvokeRetLong:
3357 case IntrinsicHelper::InvokeRetFloat:
3358 case IntrinsicHelper::InvokeRetDouble:
3359 case IntrinsicHelper::InvokeRetObject: {
3360 return Expand_Invoke(call_inst);
3361 }
Logan Chien75e4b602012-07-23 14:24:12 -07003362
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003363 //==- Math -------------------------------------------------------------==//
3364 case IntrinsicHelper::DivInt: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003365 return Expand_DivRem(call_inst, /* is_div */true, kInt);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003366 }
3367 case IntrinsicHelper::RemInt: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003368 return Expand_DivRem(call_inst, /* is_div */false, kInt);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003369 }
3370 case IntrinsicHelper::DivLong: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003371 return Expand_DivRem(call_inst, /* is_div */true, kLong);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003372 }
3373 case IntrinsicHelper::RemLong: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003374 return Expand_DivRem(call_inst, /* is_div */false, kLong);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003375 }
3376 case IntrinsicHelper::D2L: {
3377 return ExpandToRuntime(runtime_support::art_d2l, call_inst);
3378 }
3379 case IntrinsicHelper::D2I: {
3380 return ExpandToRuntime(runtime_support::art_d2i, call_inst);
3381 }
3382 case IntrinsicHelper::F2L: {
3383 return ExpandToRuntime(runtime_support::art_f2l, call_inst);
3384 }
3385 case IntrinsicHelper::F2I: {
3386 return ExpandToRuntime(runtime_support::art_f2i, call_inst);
3387 }
Logan Chien75e4b602012-07-23 14:24:12 -07003388
3389 //==- High-level Static ------------------------------------------------==//
3390 case IntrinsicHelper::HLSget: {
TDYa1275a26d442012-07-26 18:58:38 -07003391 return Expand_HLSget(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003392 }
3393 case IntrinsicHelper::HLSgetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003394 return Expand_HLSget(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003395 }
3396 case IntrinsicHelper::HLSgetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003397 return Expand_HLSget(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003398 }
3399 case IntrinsicHelper::HLSgetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003400 return Expand_HLSget(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003401 }
3402 case IntrinsicHelper::HLSgetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003403 return Expand_HLSget(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003404 }
3405 case IntrinsicHelper::HLSgetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003406 return Expand_HLSget(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003407 }
3408 case IntrinsicHelper::HLSgetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003409 return Expand_HLSget(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003410 }
3411 case IntrinsicHelper::HLSgetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003412 return Expand_HLSget(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003413 }
3414 case IntrinsicHelper::HLSgetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003415 return Expand_HLSget(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003416 }
3417 case IntrinsicHelper::HLSput: {
TDYa1275a26d442012-07-26 18:58:38 -07003418 Expand_HLSput(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003419 return NULL;
3420 }
3421 case IntrinsicHelper::HLSputBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003422 Expand_HLSput(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003423 return NULL;
3424 }
3425 case IntrinsicHelper::HLSputByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003426 Expand_HLSput(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003427 return NULL;
3428 }
3429 case IntrinsicHelper::HLSputChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003430 Expand_HLSput(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003431 return NULL;
3432 }
3433 case IntrinsicHelper::HLSputShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003434 Expand_HLSput(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003435 return NULL;
3436 }
3437 case IntrinsicHelper::HLSputFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003438 Expand_HLSput(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003439 return NULL;
3440 }
3441 case IntrinsicHelper::HLSputWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003442 Expand_HLSput(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003443 return NULL;
3444 }
3445 case IntrinsicHelper::HLSputDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003446 Expand_HLSput(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003447 return NULL;
3448 }
3449 case IntrinsicHelper::HLSputObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003450 Expand_HLSput(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003451 return NULL;
3452 }
3453
3454 //==- High-level Monitor -----------------------------------------------==//
3455 case IntrinsicHelper::MonitorEnter: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003456 Expand_MonitorEnter(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003457 return NULL;
3458 }
3459 case IntrinsicHelper::MonitorExit: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003460 Expand_MonitorExit(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003461 return NULL;
3462 }
3463
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003464 //==- Shadow Frame -----------------------------------------------------==//
3465 case IntrinsicHelper::AllocaShadowFrame: {
TDYa127ce4cc0d2012-11-18 16:59:53 -08003466 Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003467 return NULL;
3468 }
TDYa1278e950c12012-11-02 09:58:19 -07003469 case IntrinsicHelper::SetVReg: {
3470 Expand_SetVReg(call_inst.getArgOperand(0),
3471 call_inst.getArgOperand(1));
3472 return NULL;
3473 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003474 case IntrinsicHelper::PopShadowFrame: {
3475 Expand_PopShadowFrame();
3476 return NULL;
3477 }
3478 case IntrinsicHelper::UpdateDexPC: {
3479 Expand_UpdateDexPC(call_inst.getArgOperand(0));
3480 return NULL;
3481 }
TDYa127a1b21852012-07-23 03:20:39 -07003482
Logan Chien75e4b602012-07-23 14:24:12 -07003483 //==- Comparison -------------------------------------------------------==//
3484 case IntrinsicHelper::CmplFloat:
3485 case IntrinsicHelper::CmplDouble: {
3486 return Expand_FPCompare(call_inst.getArgOperand(0),
3487 call_inst.getArgOperand(1),
3488 false);
3489 }
3490 case IntrinsicHelper::CmpgFloat:
3491 case IntrinsicHelper::CmpgDouble: {
3492 return Expand_FPCompare(call_inst.getArgOperand(0),
3493 call_inst.getArgOperand(1),
3494 true);
3495 }
3496 case IntrinsicHelper::CmpLong: {
3497 return Expand_LongCompare(call_inst.getArgOperand(0),
3498 call_inst.getArgOperand(1));
3499 }
TDYa127a1b21852012-07-23 03:20:39 -07003500
Logan Chien75e4b602012-07-23 14:24:12 -07003501 //==- Const ------------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003502 case IntrinsicHelper::ConstInt:
3503 case IntrinsicHelper::ConstLong: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003504 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07003505 }
TDYa127920be7c2012-09-10 17:13:22 -07003506 case IntrinsicHelper::ConstFloat: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003507 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3508 irb_.getJFloatTy());
Logan Chien75e4b602012-07-23 14:24:12 -07003509 }
TDYa127920be7c2012-09-10 17:13:22 -07003510 case IntrinsicHelper::ConstDouble: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003511 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3512 irb_.getJDoubleTy());
3513 }
TDYa127920be7c2012-09-10 17:13:22 -07003514 case IntrinsicHelper::ConstObj: {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07003515 CHECK(LV2UInt(call_inst.getArgOperand(0)) == 0);
3516 return irb_.getJNull();
Logan Chien75e4b602012-07-23 14:24:12 -07003517 }
3518
3519 //==- Method Info ------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003520 case IntrinsicHelper::MethodInfo: {
Shih-wei Liaob2596522012-09-14 16:36:11 -07003521 // Nothing to be done, because MethodInfo carries optional hints that are
3522 // not needed by the portable path.
Logan Chien75e4b602012-07-23 14:24:12 -07003523 return NULL;
3524 }
3525
3526 //==- Copy -------------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003527 case IntrinsicHelper::CopyInt:
3528 case IntrinsicHelper::CopyFloat:
3529 case IntrinsicHelper::CopyLong:
3530 case IntrinsicHelper::CopyDouble:
3531 case IntrinsicHelper::CopyObj: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003532 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07003533 }
3534
3535 //==- Shift ------------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003536 case IntrinsicHelper::SHLLong: {
Logan Chien75e4b602012-07-23 14:24:12 -07003537 return Expand_IntegerShift(call_inst.getArgOperand(0),
3538 call_inst.getArgOperand(1),
3539 kIntegerSHL, kLong);
3540 }
TDYa127920be7c2012-09-10 17:13:22 -07003541 case IntrinsicHelper::SHRLong: {
Logan Chien75e4b602012-07-23 14:24:12 -07003542 return Expand_IntegerShift(call_inst.getArgOperand(0),
3543 call_inst.getArgOperand(1),
3544 kIntegerSHR, kLong);
3545 }
TDYa127920be7c2012-09-10 17:13:22 -07003546 case IntrinsicHelper::USHRLong: {
Logan Chien75e4b602012-07-23 14:24:12 -07003547 return Expand_IntegerShift(call_inst.getArgOperand(0),
3548 call_inst.getArgOperand(1),
3549 kIntegerUSHR, kLong);
3550 }
TDYa127920be7c2012-09-10 17:13:22 -07003551 case IntrinsicHelper::SHLInt: {
Logan Chien75e4b602012-07-23 14:24:12 -07003552 return Expand_IntegerShift(call_inst.getArgOperand(0),
3553 call_inst.getArgOperand(1),
3554 kIntegerSHL, kInt);
3555 }
TDYa127920be7c2012-09-10 17:13:22 -07003556 case IntrinsicHelper::SHRInt: {
Logan Chien75e4b602012-07-23 14:24:12 -07003557 return Expand_IntegerShift(call_inst.getArgOperand(0),
3558 call_inst.getArgOperand(1),
3559 kIntegerSHR, kInt);
3560 }
TDYa127920be7c2012-09-10 17:13:22 -07003561 case IntrinsicHelper::USHRInt: {
Logan Chien75e4b602012-07-23 14:24:12 -07003562 return Expand_IntegerShift(call_inst.getArgOperand(0),
3563 call_inst.getArgOperand(1),
3564 kIntegerUSHR, kInt);
3565 }
3566
3567 //==- Conversion -------------------------------------------------------==//
TDYa127a1b21852012-07-23 03:20:39 -07003568 case IntrinsicHelper::IntToChar: {
3569 return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
3570 irb_.getJIntTy());
3571 }
3572 case IntrinsicHelper::IntToShort: {
3573 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
3574 irb_.getJIntTy());
3575 }
3576 case IntrinsicHelper::IntToByte: {
3577 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
3578 irb_.getJIntTy());
3579 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003580
TDYa12787caa7e2012-08-25 23:23:27 -07003581 //==- Exception --------------------------------------------------------==//
3582 case IntrinsicHelper::CatchTargets: {
TDYa12755e5e6c2012-09-11 15:14:42 -07003583 UpdatePhiInstruction(current_bb_, irb_.GetInsertBlock());
TDYa12787caa7e2012-08-25 23:23:27 -07003584 llvm::SwitchInst* si = llvm::dyn_cast<llvm::SwitchInst>(call_inst.getNextNode());
3585 CHECK(si != NULL);
3586 irb_.CreateBr(si->getDefaultDest());
3587 si->eraseFromParent();
3588 return call_inst.getArgOperand(0);
3589 }
3590
Sebastien Hertz0d43d542013-02-27 19:02:16 +01003591 //==- Constructor barrier-----------------------------------------------==//
3592 case IntrinsicHelper::ConstructorBarrier: {
3593 irb_.CreateMemoryBarrier(art::kStoreStore);
3594 return NULL;
3595 }
3596
Logan Chien75e4b602012-07-23 14:24:12 -07003597 //==- Unknown Cases ----------------------------------------------------==//
3598 case IntrinsicHelper::MaxIntrinsicId:
3599 case IntrinsicHelper::UnknownId:
3600 //default:
3601 // NOTE: "default" is intentionally commented so that C/C++ compiler will
3602 // give some warning on unmatched cases.
3603 // NOTE: We should not implement these cases.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003604 break;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003605 }
Logan Chien75e4b602012-07-23 14:24:12 -07003606 UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003607 return NULL;
3608}
3609
3610} // anonymous namespace
3611
3612namespace art {
Shih-wei Liaob2596522012-09-14 16:36:11 -07003613
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003614namespace compiler_llvm {
3615
3616llvm::FunctionPass*
3617CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb) {
3618 return new GBCExpanderPass(intrinsic_helper, irb);
3619}
3620
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07003621llvm::FunctionPass*
3622CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
3623 Compiler* compiler, OatCompilationUnit* oat_compilation_unit) {
3624 if (compiler != NULL) {
3625 return new GBCExpanderPass(intrinsic_helper, irb,
3626 compiler, oat_compilation_unit);
3627 } else {
3628 return new GBCExpanderPass(intrinsic_helper, irb);
3629 }
3630}
3631
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003632} // namespace compiler_llvm
3633} // namespace art