blob: cc3c3f93f49f4c9e74b54b9adc0f7879ca1e0799 [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"
Shih-wei Liao21d28f52012-06-12 05:55:00 -070021#include "greenland/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
buzbeeefc63692012-11-14 16:31:52 -080028#include "compiler/compiler_ir.h"
buzbee449a49b2012-11-25 19:25:44 -080029#include "compiler/codegen/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
46using art::greenland::IntrinsicHelper;
47
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
128 //----------------------------------------------------------------------------
129 // Dex cache code generation helper function
130 //----------------------------------------------------------------------------
TDYa127920be7c2012-09-10 17:13:22 -0700131 llvm::Value* EmitLoadDexCacheAddr(art::MemberOffset dex_cache_offset);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700132
133 llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
134
135 llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
136
137 llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
138
139 llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
140
141 //----------------------------------------------------------------------------
142 // Code generation helper function
143 //----------------------------------------------------------------------------
144 llvm::Value* EmitLoadMethodObjectAddr();
145
146 llvm::Value* EmitLoadArrayLength(llvm::Value* array);
147
148 llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
149
150 llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
151 llvm::Value* this_addr);
152
153 llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
154 llvm::Value* index_value,
155 JType elem_jty);
156
157 private:
158 //----------------------------------------------------------------------------
159 // Expand Greenland intrinsics
160 //----------------------------------------------------------------------------
161 void Expand_TestSuspend(llvm::CallInst& call_inst);
162
TDYa1279a129452012-07-19 03:10:08 -0700163 void Expand_MarkGCCard(llvm::CallInst& call_inst);
164
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700165 llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
166
167 llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
168
169 void Expand_LockObject(llvm::Value* obj);
170
171 void Expand_UnlockObject(llvm::Value* obj);
172
173 llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
174 llvm::Value* index_value,
175 JType elem_jty);
176
177 void Expand_ArrayPut(llvm::Value* new_value,
178 llvm::Value* array_addr,
179 llvm::Value* index_value,
180 JType elem_jty);
181
182 void Expand_FilledNewArray(llvm::CallInst& call_inst);
183
184 llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
185 llvm::Value* is_volatile_value,
186 llvm::Value* object_addr,
187 JType field_jty);
188
189 void Expand_IPutFast(llvm::Value* field_offset_value,
190 llvm::Value* is_volatile_value,
191 llvm::Value* object_addr,
192 llvm::Value* new_value,
193 JType field_jty);
194
195 llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
196 llvm::Value* field_offset_value,
197 llvm::Value* is_volatile_value,
198 JType field_jty);
199
200 void Expand_SPutFast(llvm::Value* static_storage_addr,
201 llvm::Value* field_offset_value,
202 llvm::Value* is_volatile_value,
203 llvm::Value* new_value,
204 JType field_jty);
205
206 llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
207
208 llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
209
210 llvm::Value*
211 Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
212
213 llvm::Value*
214 Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
215 llvm::Value* this_addr);
216
217 llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
218
TDYa1274ec8ccd2012-08-11 07:04:57 -0700219 llvm::Value* Expand_DivRem(llvm::CallInst& call_inst, bool is_div, JType op_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700220
TDYa127ce4cc0d2012-11-18 16:59:53 -0800221 void Expand_AllocaShadowFrame(llvm::Value* num_vregs_value);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700222
TDYa1278e950c12012-11-02 09:58:19 -0700223 void Expand_SetVReg(llvm::Value* entry_idx, llvm::Value* obj);
224
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700225 void Expand_PopShadowFrame();
226
227 void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
228
TDYa127a1b21852012-07-23 03:20:39 -0700229 //----------------------------------------------------------------------------
230 // Quick
231 //----------------------------------------------------------------------------
232
233 llvm::Value* Expand_FPCompare(llvm::Value* src1_value,
234 llvm::Value* src2_value,
235 bool gt_bias);
236
237 llvm::Value* Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value);
238
239 llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
240 llvm::Value* cmp_lt);
241
TDYa127f71bf5a2012-07-29 20:09:52 -0700242 llvm::Value* EmitLoadConstantClass(uint32_t dex_pc, uint32_t type_idx);
TDYa1275a26d442012-07-26 18:58:38 -0700243 llvm::Value* EmitLoadStaticStorage(uint32_t dex_pc, uint32_t type_idx);
244
TDYa1275e869b62012-07-25 00:45:39 -0700245 llvm::Value* Expand_HLIGet(llvm::CallInst& call_inst, JType field_jty);
246 void Expand_HLIPut(llvm::CallInst& call_inst, JType field_jty);
247
TDYa1275a26d442012-07-26 18:58:38 -0700248 llvm::Value* Expand_HLSget(llvm::CallInst& call_inst, JType field_jty);
249 void Expand_HLSput(llvm::CallInst& call_inst, JType field_jty);
250
251 llvm::Value* Expand_HLArrayGet(llvm::CallInst& call_inst, JType field_jty);
252 void Expand_HLArrayPut(llvm::CallInst& call_inst, JType field_jty);
253
TDYa127f71bf5a2012-07-29 20:09:52 -0700254 llvm::Value* Expand_ConstString(llvm::CallInst& call_inst);
255 llvm::Value* Expand_ConstClass(llvm::CallInst& call_inst);
256
257 void Expand_MonitorEnter(llvm::CallInst& call_inst);
258 void Expand_MonitorExit(llvm::CallInst& call_inst);
259
260 void Expand_HLCheckCast(llvm::CallInst& call_inst);
261 llvm::Value* Expand_InstanceOf(llvm::CallInst& call_inst);
262
263 llvm::Value* Expand_NewInstance(llvm::CallInst& call_inst);
264
265 llvm::Value* Expand_HLInvoke(llvm::CallInst& call_inst);
266
267 llvm::Value* Expand_OptArrayLength(llvm::CallInst& call_inst);
268 llvm::Value* Expand_NewArray(llvm::CallInst& call_inst);
269 llvm::Value* Expand_HLFilledNewArray(llvm::CallInst& call_inst);
270 void Expand_HLFillArrayData(llvm::CallInst& call_inst);
271
272 llvm::Value* EmitAllocNewArray(uint32_t dex_pc,
273 llvm::Value* array_length_value,
274 uint32_t type_idx,
275 bool is_filled_new_array);
276
277 llvm::Value* EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
TDYa127920be7c2012-09-10 17:13:22 -0700278 art::InvokeType invoke_type,
TDYa127f71bf5a2012-07-29 20:09:52 -0700279 llvm::Value* this_addr,
280 uint32_t dex_pc,
281 bool is_fast_path);
282
TDYa1275e869b62012-07-25 00:45:39 -0700283 void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
284
285 void EmitUpdateDexPC(uint32_t dex_pc);
286
287 void EmitGuard_DivZeroException(uint32_t dex_pc,
288 llvm::Value* denominator,
289 JType op_jty);
290
291 void EmitGuard_NullPointerException(uint32_t dex_pc,
292 llvm::Value* object);
293
294 void EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
295 llvm::Value* array,
296 llvm::Value* index);
297
TDYa1275e869b62012-07-25 00:45:39 -0700298 llvm::FunctionType* GetFunctionType(uint32_t method_idx, bool is_static);
299
300 llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
301
302 llvm::BasicBlock* CreateBasicBlockWithDexPC(uint32_t dex_pc,
303 const char* postfix);
304
305 int32_t GetTryItemOffset(uint32_t dex_pc);
306
307 llvm::BasicBlock* GetLandingPadBasicBlock(uint32_t dex_pc);
308
309 llvm::BasicBlock* GetUnwindBasicBlock();
310
311 void EmitGuard_ExceptionLandingPad(uint32_t dex_pc);
312
313 void EmitBranchExceptionLandingPad(uint32_t dex_pc);
314
Logan Chien75e4b602012-07-23 14:24:12 -0700315 //----------------------------------------------------------------------------
316 // Expand Arithmetic Helper Intrinsics
317 //----------------------------------------------------------------------------
318
319 llvm::Value* Expand_IntegerShift(llvm::Value* src1_value,
320 llvm::Value* src2_value,
321 IntegerShiftKind kind,
322 JType op_jty);
323
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700324 public:
325 static char ID;
326
327 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb)
328 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
Logan Chiene5b8f8b2012-08-13 11:45:05 +0800329 context_(irb.getContext()), rtb_(irb.Runtime()),
TDYa1278e950c12012-11-02 09:58:19 -0700330 shadow_frame_(NULL), old_shadow_frame_(NULL),
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700331 compiler_(NULL), dex_file_(NULL), code_item_(NULL),
Logan Chien67645d82012-08-17 09:10:54 +0800332 oat_compilation_unit_(NULL), method_idx_(-1u), func_(NULL),
333 changed_(false)
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700334 { }
335
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700336 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
TDYa127920be7c2012-09-10 17:13:22 -0700337 art::Compiler* compiler, art::OatCompilationUnit* oat_compilation_unit)
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700338 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
339 context_(irb.getContext()), rtb_(irb.Runtime()),
TDYa1278e950c12012-11-02 09:58:19 -0700340 shadow_frame_(NULL), old_shadow_frame_(NULL),
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700341 compiler_(compiler),
342 dex_file_(oat_compilation_unit->GetDexFile()),
343 code_item_(oat_compilation_unit->GetCodeItem()),
344 oat_compilation_unit_(oat_compilation_unit),
345 method_idx_(oat_compilation_unit->GetDexMethodIndex()),
346 func_(NULL), changed_(false)
347 { }
348
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700349 bool runOnFunction(llvm::Function& func);
350
351 private:
Logan Chien67645d82012-08-17 09:10:54 +0800352 void InsertStackOverflowCheck(llvm::Function& func);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700353
354 llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
355 llvm::CallInst& call_inst);
356
357};
358
359char GBCExpanderPass::ID = 0;
360
361bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
TDYa127b672d1e2012-06-28 21:21:45 -0700362 // Runtime support or stub
363 if (func.getName().startswith("art_") || func.getName().startswith("Art")) {
364 return false;
365 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700366
Logan Chien67645d82012-08-17 09:10:54 +0800367 // Setup rewrite context
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700368 shadow_frame_ = NULL;
369 old_shadow_frame_ = NULL;
TDYa1275e869b62012-07-25 00:45:39 -0700370 func_ = &func;
Logan Chien67645d82012-08-17 09:10:54 +0800371 changed_ = false; // Assume unchanged
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700372
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700373 basic_blocks_.resize(code_item_->insns_size_in_code_units_);
374 basic_block_landing_pads_.resize(code_item_->tries_size_, NULL);
375 basic_block_unwind_ = NULL;
376 for (llvm::Function::iterator bb_iter = func_->begin(), bb_end = func_->end();
377 bb_iter != bb_end;
378 ++bb_iter) {
379 if (bb_iter->begin()->getMetadata("DexOff") == NULL) {
380 continue;
381 }
382 uint32_t dex_pc = LV2UInt(bb_iter->begin()->getMetadata("DexOff")->getOperand(0));
383 basic_blocks_[dex_pc] = bb_iter;
384 }
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -0700385
Logan Chien67645d82012-08-17 09:10:54 +0800386 // Insert stack overflow check
387 InsertStackOverflowCheck(func); // TODO: Use intrinsic.
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700388
Logan Chien67645d82012-08-17 09:10:54 +0800389 // Rewrite the intrinsics
390 RewriteFunction();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700391
392 VERIFY_LLVM_FUNCTION(func);
393
Logan Chien67645d82012-08-17 09:10:54 +0800394 return changed_;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700395}
396
Logan Chien67645d82012-08-17 09:10:54 +0800397void GBCExpanderPass::RewriteBasicBlock(llvm::BasicBlock* original_block) {
398 llvm::BasicBlock* curr_basic_block = original_block;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700399
Logan Chien67645d82012-08-17 09:10:54 +0800400 llvm::BasicBlock::iterator inst_iter = original_block->begin();
401 llvm::BasicBlock::iterator inst_end = original_block->end();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700402
Logan Chien67645d82012-08-17 09:10:54 +0800403 while (inst_iter != inst_end) {
404 llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst_iter);
405 IntrinsicHelper::IntrinsicId intr_id = IntrinsicHelper::UnknownId;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700406
Logan Chien67645d82012-08-17 09:10:54 +0800407 if (call_inst) {
408 llvm::Function* callee_func = call_inst->getCalledFunction();
409 intr_id = intrinsic_helper_.GetIntrinsicId(callee_func);
410 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700411
Logan Chien67645d82012-08-17 09:10:54 +0800412 if (intr_id == IntrinsicHelper::UnknownId) {
413 // This is not intrinsic call. Skip this instruction.
414 ++inst_iter;
415 continue;
416 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700417
Logan Chien67645d82012-08-17 09:10:54 +0800418 // Rewrite the intrinsic and change the function
419 changed_ = true;
420 irb_.SetInsertPoint(inst_iter);
421
422 // Expand the intrinsic
423 if (llvm::Value* new_value = ExpandIntrinsic(intr_id, *call_inst)) {
424 inst_iter->replaceAllUsesWith(new_value);
425 }
426
427 // Remove the old intrinsic call instruction
428 llvm::BasicBlock::iterator old_inst = inst_iter++;
429 old_inst->eraseFromParent();
430
431 // Splice the instruction to the new basic block
432 llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
433 if (next_basic_block != curr_basic_block) {
434 next_basic_block->getInstList().splice(
435 irb_.GetInsertPoint(), curr_basic_block->getInstList(),
436 inst_iter, inst_end);
437 curr_basic_block = next_basic_block;
438 inst_end = curr_basic_block->end();
439 }
440 }
441}
442
443
444void GBCExpanderPass::RewriteFunction() {
445 size_t num_basic_blocks = func_->getBasicBlockList().size();
446 // NOTE: We are not using (bb_iter != bb_end) as the for-loop condition,
447 // because we will create new basic block while expanding the intrinsics.
448 // We only want to iterate through the input basic blocks.
449
TDYa127aa558872012-08-16 05:11:07 -0700450 landing_pad_phi_mapping_.clear();
451
Logan Chien67645d82012-08-17 09:10:54 +0800452 for (llvm::Function::iterator bb_iter = func_->begin();
453 num_basic_blocks > 0; ++bb_iter, --num_basic_blocks) {
Shih-wei Liao627d8c42012-08-24 08:31:18 -0700454 // Set insert point to current basic block.
455 irb_.SetInsertPoint(bb_iter);
Logan Chien67645d82012-08-17 09:10:54 +0800456
TDYa12755e5e6c2012-09-11 15:14:42 -0700457 current_bb_ = bb_iter;
TDYa127aa558872012-08-16 05:11:07 -0700458
Logan Chien67645d82012-08-17 09:10:54 +0800459 // Rewrite the basic block
460 RewriteBasicBlock(bb_iter);
461
462 // Update the phi-instructions in the successor basic block
463 llvm::BasicBlock* last_block = irb_.GetInsertBlock();
464 if (last_block != bb_iter) {
465 UpdatePhiInstruction(bb_iter, last_block);
466 }
467 }
TDYa127aa558872012-08-16 05:11:07 -0700468
469 typedef std::map<llvm::PHINode*, llvm::PHINode*> HandlerPHIMap;
470 HandlerPHIMap handler_phi;
471 // Iterate every used landing pad basic block
472 for (size_t i = 0, ei = basic_block_landing_pads_.size(); i != ei; ++i) {
473 llvm::BasicBlock* lbb = basic_block_landing_pads_[i];
474 if (lbb == NULL) {
475 continue;
476 }
477
478 llvm::TerminatorInst* term_inst = lbb->getTerminator();
479 std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*> >& rewrite_pair
480 = landing_pad_phi_mapping_[lbb];
481 irb_.SetInsertPoint(lbb->begin());
482
483 // Iterate every succeeding basic block (catch block)
484 for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
485 succ_iter != succ_end; ++succ_iter) {
486 llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
487
488 // Iterate every phi instructions in the succeeding basic block
489 for (llvm::BasicBlock::iterator
490 inst_iter = succ_basic_block->begin(),
491 inst_end = succ_basic_block->end();
492 inst_iter != inst_end; ++inst_iter) {
493 llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
494
495 if (!phi) {
496 break; // Meet non-phi instruction. Done.
497 }
498
499 if (handler_phi[phi] == NULL) {
500 handler_phi[phi] = llvm::PHINode::Create(phi->getType(), 1);
501 }
502
503 // Create new_phi in landing pad
504 llvm::PHINode* new_phi = irb_.CreatePHI(phi->getType(), rewrite_pair.size());
505 // Insert all incoming value into new_phi by rewrite_pair
506 for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
507 llvm::BasicBlock* old_bb = rewrite_pair[j].first;
508 llvm::BasicBlock* new_bb = rewrite_pair[j].second;
509 new_phi->addIncoming(phi->getIncomingValueForBlock(old_bb), new_bb);
510 }
511 // Delete all incoming value from 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 int old_bb_idx = phi->getBasicBlockIndex(old_bb);
515 if (old_bb_idx >= 0) {
516 phi->removeIncomingValue(old_bb_idx, false);
517 }
518 }
519 // Insert new_phi into new handler phi
520 handler_phi[phi]->addIncoming(new_phi, lbb);
521 }
522 }
523 }
524
525 // Replace all handler phi
526 // We can't just use the old handler phi, because some exception edges will disappear after we
527 // compute fast-path.
528 for (HandlerPHIMap::iterator it = handler_phi.begin(); it != handler_phi.end(); ++it) {
529 llvm::PHINode* old_phi = it->first;
530 llvm::PHINode* new_phi = it->second;
531 new_phi->insertBefore(old_phi);
532 old_phi->replaceAllUsesWith(new_phi);
533 old_phi->eraseFromParent();
534 }
Logan Chien67645d82012-08-17 09:10:54 +0800535}
536
537void GBCExpanderPass::UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
538 llvm::BasicBlock* new_basic_block) {
539 llvm::TerminatorInst* term_inst = new_basic_block->getTerminator();
540
541 if (!term_inst) {
542 return; // No terminating instruction in new_basic_block. Nothing to do.
543 }
544
545 // Iterate every succeeding basic block
546 for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
547 succ_iter != succ_end; ++succ_iter) {
548 llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
549
550 // Iterate every phi instructions in the succeeding basic block
551 for (llvm::BasicBlock::iterator
552 inst_iter = succ_basic_block->begin(),
553 inst_end = succ_basic_block->end();
554 inst_iter != inst_end; ++inst_iter) {
555 llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
556
557 if (!phi) {
558 break; // Meet non-phi instruction. Done.
559 }
560
561 // Update the incoming block of this phi instruction
562 for (llvm::PHINode::block_iterator
563 ibb_iter = phi->block_begin(), ibb_end = phi->block_end();
564 ibb_iter != ibb_end; ++ibb_iter) {
565 if (*ibb_iter == old_basic_block) {
566 *ibb_iter = new_basic_block;
567 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700568 }
569 }
570 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700571}
572
573llvm::Value* GBCExpanderPass::ExpandToRuntime(runtime_support::RuntimeId rt,
574 llvm::CallInst& inst) {
575 // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
576 // the arguments passed to the GBC intrinsic are as the same as IBC runtime
577 // function, therefore only called function is needed to change.
578 unsigned num_args = inst.getNumArgOperands();
579
580 if (num_args <= 0) {
581 return irb_.CreateCall(irb_.GetRuntime(rt));
582 } else {
583 std::vector<llvm::Value*> args;
584 for (unsigned i = 0; i < num_args; i++) {
585 args.push_back(inst.getArgOperand(i));
586 }
587
588 return irb_.CreateCall(irb_.GetRuntime(rt), args);
589 }
590}
591
Logan Chien67645d82012-08-17 09:10:54 +0800592void
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700593GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
594 llvm::Function* func = first_non_alloca->getParent()->getParent();
595 llvm::Module* module = func->getParent();
596
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700597 // Call llvm intrinsic function to get frame address.
598 llvm::Function* frameaddress =
599 llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
600
601 // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
602 llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
603
604 // Cast i8* to int
605 frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
606
607 // Get thread.stack_end_
608 llvm::Value* stack_end =
TDYa127920be7c2012-09-10 17:13:22 -0700609 irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::StackEndOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700610 irb_.getPtrEquivIntTy(),
611 kTBAARuntimeInfo);
612
613 // Check the frame address < thread.stack_end_ ?
614 llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
615
616 llvm::BasicBlock* block_exception =
617 llvm::BasicBlock::Create(context_, "stack_overflow", func);
618
619 llvm::BasicBlock* block_continue =
620 llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
621
622 irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
623
624 // If stack overflow, throw exception.
625 irb_.SetInsertPoint(block_exception);
626 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowStackOverflowException));
627
628 // Unwind.
629 llvm::Type* ret_type = func->getReturnType();
630 if (ret_type->isVoidTy()) {
631 irb_.CreateRetVoid();
632 } else {
633 // The return value is ignored when there's an exception. MethodCompiler
634 // returns zero value under the the corresponding return type in this case.
635 // GBCExpander returns LLVM undef value here for brevity
636 irb_.CreateRet(llvm::UndefValue::get(ret_type));
637 }
638
639 irb_.SetInsertPoint(block_continue);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700640}
641
TDYa127920be7c2012-09-10 17:13:22 -0700642llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(art::MemberOffset offset) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700643 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
644
645 return irb_.LoadFromObjectOffset(method_object_addr,
646 offset.Int32Value(),
647 irb_.getJObjectTy(),
648 kTBAAConstJObject);
649}
650
651llvm::Value*
652GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
653 llvm::Value* static_storage_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800654 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheInitializedStaticStorageOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700655
656 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
657
658 return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
659}
660
661llvm::Value*
662GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
663 llvm::Value* resolved_type_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800664 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedTypesOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700665
666 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
667
668 return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
669}
670
671llvm::Value* GBCExpanderPass::
672EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
673 llvm::Value* resolved_method_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800674 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheResolvedMethodsOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700675
676 llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
677
678 return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
679}
680
681llvm::Value* GBCExpanderPass::
682EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
683 llvm::Value* string_dex_cache_addr =
Ian Rogers98573f92013-01-30 17:26:32 -0800684 EmitLoadDexCacheAddr(art::mirror::AbstractMethod::DexCacheStringsOffset());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700685
686 llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
687
688 return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
689}
690
691llvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
692 llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
693 return parent_func->arg_begin();
694}
695
696llvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
697 // Load array length
698 return irb_.LoadFromObjectOffset(array,
Ian Rogers98573f92013-01-30 17:26:32 -0800699 art::mirror::Array::LengthOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700700 irb_.getJIntTy(),
701 kTBAAConstJObject);
702
703}
704
705llvm::Value*
706GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
707 llvm::Value* callee_method_object_field_addr =
708 EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
709
TDYa127ce4cc0d2012-11-18 16:59:53 -0800710 return irb_.CreateLoad(callee_method_object_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700711}
712
713llvm::Value* GBCExpanderPass::
714EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
715 // Load class object of *this* pointer
716 llvm::Value* class_object_addr =
717 irb_.LoadFromObjectOffset(this_addr,
Ian Rogers98573f92013-01-30 17:26:32 -0800718 art::mirror::Object::ClassOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700719 irb_.getJObjectTy(),
720 kTBAAConstJObject);
721
722 // Load vtable address
723 llvm::Value* vtable_addr =
724 irb_.LoadFromObjectOffset(class_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -0800725 art::mirror::Class::VTableOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700726 irb_.getJObjectTy(),
727 kTBAAConstJObject);
728
729 // Load callee method object
730 llvm::Value* vtable_idx_value =
731 irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
732
733 llvm::Value* method_field_addr =
734 EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
735
736 return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
737}
738
739// Emit Array GetElementPtr
740llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
741 llvm::Value* index_value,
742 JType elem_jty) {
743
744 int data_offset;
745 if (elem_jty == kLong || elem_jty == kDouble ||
Ian Rogers98573f92013-01-30 17:26:32 -0800746 (elem_jty == kObject && sizeof(uint64_t) == sizeof(art::mirror::Object*))) {
747 data_offset = art::mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700748 } else {
Ian Rogers98573f92013-01-30 17:26:32 -0800749 data_offset = art::mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700750 }
751
752 llvm::Constant* data_offset_value =
753 irb_.getPtrEquivInt(data_offset);
754
755 llvm::Type* elem_type = irb_.getJType(elem_jty, kArray);
756
757 llvm::Value* array_data_addr =
758 irb_.CreatePtrDisp(array_addr, data_offset_value,
759 elem_type->getPointerTo());
760
761 return irb_.CreateGEP(array_data_addr, index_value);
762}
763
764void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
TDYa127ce4cc0d2012-11-18 16:59:53 -0800765 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
766
767 llvm::Value* suspend_count =
768 irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::ThreadFlagsOffset().Int32Value(),
769 irb_.getInt16Ty(),
770 kTBAARuntimeInfo);
771 llvm::Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
772
773 llvm::BasicBlock* basic_block_suspend = CreateBasicBlockWithDexPC(dex_pc, "suspend");
774 llvm::BasicBlock* basic_block_cont = CreateBasicBlockWithDexPC(dex_pc, "suspend_cont");
775
776 irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
777
778 irb_.SetInsertPoint(basic_block_suspend);
779 if (dex_pc != art::DexFile::kDexNoIndex) {
780 EmitUpdateDexPC(dex_pc);
781 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700782 irb_.Runtime().EmitTestSuspend();
TDYa127ce4cc0d2012-11-18 16:59:53 -0800783 irb_.CreateBr(basic_block_cont);
784
785 irb_.SetInsertPoint(basic_block_cont);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700786 return;
787}
788
TDYa1279a129452012-07-19 03:10:08 -0700789void GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
TDYa1279a129452012-07-19 03:10:08 -0700790 irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
TDYa1279a129452012-07-19 03:10:08 -0700791 return;
792}
793
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700794llvm::Value*
795GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
796 uint32_t string_idx =
797 llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
798
799 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
800
TDYa127ce4cc0d2012-11-18 16:59:53 -0800801 return irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700802}
803
804llvm::Value*
805GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
806 uint32_t type_idx =
807 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
808
809 llvm::Value* type_field_addr =
810 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
811
TDYa127ce4cc0d2012-11-18 16:59:53 -0800812 return irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700813}
814
815void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700816 rtb_.EmitLockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700817 return;
818}
819
820void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700821 rtb_.EmitUnlockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700822 return;
823}
824
825llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
826 llvm::Value* index_value,
827 JType elem_jty) {
828 llvm::Value* array_elem_addr =
829 EmitArrayGEP(array_addr, index_value, elem_jty);
830
831 return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
832}
833
834void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
835 llvm::Value* array_addr,
836 llvm::Value* index_value,
837 JType elem_jty) {
838 llvm::Value* array_elem_addr =
839 EmitArrayGEP(array_addr, index_value, elem_jty);
840
841 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
842
843 return;
844}
845
846void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
847 // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
848 llvm::Value* array = call_inst.getArgOperand(0);
849
850 uint32_t element_jty =
851 llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
852
853 DCHECK(call_inst.getNumArgOperands() > 2);
854 unsigned num_elements = (call_inst.getNumArgOperands() - 2);
855
856 bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
857
858 uint32_t alignment;
859 llvm::Constant* elem_size;
860 llvm::PointerType* field_type;
861
862 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
863 // as the element, thus we are only checking 2 cases: primitive int and
864 // non-primitive type.
865 if (is_elem_int_ty) {
866 alignment = sizeof(int32_t);
867 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
868 field_type = irb_.getJIntTy()->getPointerTo();
869 } else {
870 alignment = irb_.getSizeOfPtrEquivInt();
871 elem_size = irb_.getSizeOfPtrEquivIntValue();
872 field_type = irb_.getJObjectTy()->getPointerTo();
873 }
874
875 llvm::Value* data_field_offset =
Ian Rogers98573f92013-01-30 17:26:32 -0800876 irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700877
878 llvm::Value* data_field_addr =
879 irb_.CreatePtrDisp(array, data_field_offset, field_type);
880
881 for (unsigned i = 0; i < num_elements; ++i) {
882 // Values to fill the array begin at the 3rd argument
883 llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
884
885 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
886
887 data_field_addr =
888 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
889 }
890
891 return;
892}
893
894llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
895 llvm::Value* /*is_volatile_value*/,
896 llvm::Value* object_addr,
897 JType field_jty) {
898 int field_offset =
899 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
900
901 DCHECK_GE(field_offset, 0);
902
903 llvm::PointerType* field_type =
904 irb_.getJType(field_jty, kField)->getPointerTo();
905
906 field_offset_value = irb_.getPtrEquivInt(field_offset);
907
908 llvm::Value* field_addr =
909 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
910
911 // TODO: Check is_volatile. We need to generate atomic load instruction
912 // when is_volatile is true.
913 return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
914}
915
916void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
917 llvm::Value* /* is_volatile_value */,
918 llvm::Value* object_addr,
919 llvm::Value* new_value,
920 JType field_jty) {
921 int field_offset =
922 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
923
924 DCHECK_GE(field_offset, 0);
925
926 llvm::PointerType* field_type =
927 irb_.getJType(field_jty, kField)->getPointerTo();
928
929 field_offset_value = irb_.getPtrEquivInt(field_offset);
930
931 llvm::Value* field_addr =
932 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
933
934 // TODO: Check is_volatile. We need to generate atomic store instruction
935 // when is_volatile is true.
936 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
937
938 return;
939}
940
941llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
942 llvm::Value* field_offset_value,
943 llvm::Value* /*is_volatile_value*/,
944 JType field_jty) {
945 int field_offset =
946 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
947
948 DCHECK_GE(field_offset, 0);
949
950 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
951
952 llvm::Value* static_field_addr =
953 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
954 irb_.getJType(field_jty, kField)->getPointerTo());
955
956 // TODO: Check is_volatile. We need to generate atomic store instruction
957 // when is_volatile is true.
958 return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
959}
960
961void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
962 llvm::Value* field_offset_value,
963 llvm::Value* /* is_volatile_value */,
964 llvm::Value* new_value,
965 JType field_jty) {
966 int field_offset =
967 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
968
969 DCHECK_GE(field_offset, 0);
970
971 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
972
973 llvm::Value* static_field_addr =
974 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
975 irb_.getJType(field_jty, kField)->getPointerTo());
976
977 // TODO: Check is_volatile. We need to generate atomic store instruction
978 // when is_volatile is true.
979 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
980
981 return;
982}
983
984llvm::Value*
985GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
986 return irb_.LoadFromObjectOffset(method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -0800987 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700988 irb_.getJObjectTy(),
989 kTBAAConstJObject);
990}
991
992llvm::Value*
993GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
994 uint32_t type_idx =
995 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
996
997 llvm::Value* storage_field_addr =
998 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
999
TDYa127ce4cc0d2012-11-18 16:59:53 -08001000 return irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001001}
1002
1003llvm::Value*
1004GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
1005 uint32_t callee_method_idx =
1006 llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
1007
1008 return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
1009}
1010
1011llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
1012 llvm::Value* vtable_idx_value,
1013 llvm::Value* this_addr) {
1014 int vtable_idx =
1015 llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
1016
1017 return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
1018}
1019
1020llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
1021 // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
1022 llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
1023 unsigned num_args = call_inst.getNumArgOperands();
1024 llvm::Type* ret_type = call_inst.getType();
1025
1026 // Determine the function type of the callee method
1027 std::vector<llvm::Type*> args_type;
1028 std::vector<llvm::Value*> args;
1029 for (unsigned i = 0; i < num_args; i++) {
1030 args.push_back(call_inst.getArgOperand(i));
1031 args_type.push_back(args[i]->getType());
1032 }
1033
1034 llvm::FunctionType* callee_method_type =
1035 llvm::FunctionType::get(ret_type, args_type, false);
1036
1037 llvm::Value* code_addr =
1038 irb_.LoadFromObjectOffset(callee_method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001039 art::mirror::AbstractMethod::GetCodeOffset().Int32Value(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001040 callee_method_type->getPointerTo(),
TDYa127ce4cc0d2012-11-18 16:59:53 -08001041 kTBAARuntimeInfo);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001042
1043 // Invoke callee
1044 llvm::Value* retval = irb_.CreateCall(code_addr, args);
1045
1046 return retval;
1047}
1048
TDYa1274ec8ccd2012-08-11 07:04:57 -07001049llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::CallInst& call_inst,
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001050 bool is_div, JType op_jty) {
TDYa1274ec8ccd2012-08-11 07:04:57 -07001051 llvm::Value* dividend = call_inst.getArgOperand(0);
1052 llvm::Value* divisor = call_inst.getArgOperand(1);
TDYa1274ec8ccd2012-08-11 07:04:57 -07001053 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1054 EmitGuard_DivZeroException(dex_pc, divisor, op_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001055 // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
1056
1057 // Check the special case: MININT / -1 = MININT
1058 // That case will cause overflow, which is undefined behavior in llvm.
1059 // So we check the divisor is -1 or not, if the divisor is -1, we do
1060 // the special path to avoid undefined behavior.
1061 llvm::Type* op_type = irb_.getJType(op_jty, kAccurate);
1062 llvm::Value* zero = irb_.getJZero(op_jty);
1063 llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
1064
TDYa1275e869b62012-07-25 00:45:39 -07001065 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001066 llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
1067 llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
1068 llvm::BasicBlock* neg_one_cont =
1069 llvm::BasicBlock::Create(context_, "", parent);
1070
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001071 llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
1072 irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
1073
1074 // If divisor == -1
1075 irb_.SetInsertPoint(eq_neg_one);
1076 llvm::Value* eq_result;
1077 if (is_div) {
1078 // We can just change from "dividend div -1" to "neg dividend". The sub
1079 // don't care the sign/unsigned because of two's complement representation.
1080 // And the behavior is what we want:
1081 // -(2^n) (2^n)-1
1082 // MININT < k <= MAXINT -> mul k -1 = -k
1083 // MININT == k -> mul k -1 = k
1084 //
1085 // LLVM use sub to represent 'neg'
1086 eq_result = irb_.CreateSub(zero, dividend);
1087 } else {
1088 // Everything modulo -1 will be 0.
1089 eq_result = zero;
1090 }
1091 irb_.CreateBr(neg_one_cont);
1092
1093 // If divisor != -1, just do the division.
1094 irb_.SetInsertPoint(ne_neg_one);
1095 llvm::Value* ne_result;
1096 if (is_div) {
1097 ne_result = irb_.CreateSDiv(dividend, divisor);
1098 } else {
1099 ne_result = irb_.CreateSRem(dividend, divisor);
1100 }
1101 irb_.CreateBr(neg_one_cont);
1102
1103 irb_.SetInsertPoint(neg_one_cont);
1104 llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
1105 result->addIncoming(eq_result, eq_neg_one);
1106 result->addIncoming(ne_result, ne_neg_one);
1107
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001108 return result;
1109}
1110
TDYa127ce4cc0d2012-11-18 16:59:53 -08001111void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_vregs_value) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001112 // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
1113 // MethodCompiler::EmitPushShadowFrame
TDYa1278e950c12012-11-02 09:58:19 -07001114 uint16_t num_vregs =
1115 llvm::cast<llvm::ConstantInt>(num_vregs_value)->getZExtValue();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001116
1117 llvm::StructType* shadow_frame_type =
TDYa127ce4cc0d2012-11-18 16:59:53 -08001118 irb_.getShadowFrameTy(num_vregs);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001119
1120 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
1121
1122 // Alloca a pointer to old shadow frame
1123 old_shadow_frame_ =
1124 irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
1125
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001126 // Push the shadow frame
1127 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1128
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001129 llvm::Value* shadow_frame_upcast =
1130 irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
1131
1132 llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
1133 method_object_addr,
TDYa1278e950c12012-11-02 09:58:19 -07001134 num_vregs);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001135
1136 irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
1137
1138 return;
1139}
1140
TDYa1278e950c12012-11-02 09:58:19 -07001141void GBCExpanderPass::Expand_SetVReg(llvm::Value* entry_idx,
1142 llvm::Value* value) {
1143 DCHECK(shadow_frame_ != NULL);
1144
1145 llvm::Value* gep_index[] = {
1146 irb_.getInt32(0), // No pointer displacement
TDYa127ce4cc0d2012-11-18 16:59:53 -08001147 irb_.getInt32(1), // VRegs
TDYa1278e950c12012-11-02 09:58:19 -07001148 entry_idx // Pointer field
1149 };
1150
1151 llvm::Value* vreg_addr = irb_.CreateGEP(shadow_frame_, gep_index);
1152
1153 irb_.CreateStore(value,
1154 irb_.CreateBitCast(vreg_addr, value->getType()->getPointerTo()),
1155 kTBAAShadowFrame);
1156 return;
1157}
1158
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001159void GBCExpanderPass::Expand_PopShadowFrame() {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001160 if (old_shadow_frame_ == NULL) {
1161 return;
1162 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001163 rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
1164 return;
1165}
1166
1167void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
1168 irb_.StoreToObjectOffset(shadow_frame_,
TDYa127920be7c2012-09-10 17:13:22 -07001169 art::ShadowFrame::DexPCOffset(),
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001170 dex_pc_value,
1171 kTBAAShadowFrame);
1172 return;
1173}
1174
Logan Chien67645d82012-08-17 09:10:54 +08001175void GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
jeffhao40283122013-01-15 13:15:24 -08001176 // All alloca instructions are generated in the first basic block of the
1177 // function, and there are no alloca instructions after the first non-alloca
1178 // instruction.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001179
Logan Chien67645d82012-08-17 09:10:54 +08001180 llvm::BasicBlock* first_basic_block = &func.front();
1181
1182 // Look for first non-alloca instruction
1183 llvm::BasicBlock::iterator first_non_alloca = first_basic_block->begin();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001184 while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
1185 ++first_non_alloca;
1186 }
1187
Logan Chien67645d82012-08-17 09:10:54 +08001188 irb_.SetInsertPoint(first_non_alloca);
1189
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001190 // Insert stack overflow check codes before first_non_alloca (i.e., after all
1191 // alloca instructions)
Logan Chien67645d82012-08-17 09:10:54 +08001192 EmitStackOverflowCheck(&*first_non_alloca);
1193
TDYa127890ea892012-08-22 10:49:42 -07001194 irb_.Runtime().EmitTestSuspend();
TDYa127890ea892012-08-22 10:49:42 -07001195
Logan Chien67645d82012-08-17 09:10:54 +08001196 llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
1197 if (next_basic_block != first_basic_block) {
1198 // Splice the rest of the instruction to the continuing basic block
1199 next_basic_block->getInstList().splice(
1200 irb_.GetInsertPoint(), first_basic_block->getInstList(),
1201 first_non_alloca, first_basic_block->end());
1202
1203 // Rewrite the basic block
1204 RewriteBasicBlock(next_basic_block);
1205
1206 // Update the phi-instructions in the successor basic block
1207 UpdatePhiInstruction(first_basic_block, irb_.GetInsertBlock());
1208 }
1209
1210 // We have changed the basic block
1211 changed_ = true;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001212}
1213
TDYa1275e869b62012-07-25 00:45:39 -07001214// ==== High-level intrinsic expander ==========================================
1215
TDYa127a1b21852012-07-23 03:20:39 -07001216llvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
1217 llvm::Value* src2_value,
1218 bool gt_bias) {
1219 llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
1220 llvm::Value* cmp_lt;
1221
1222 if (gt_bias) {
1223 cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
1224 } else {
1225 cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
1226 }
1227
1228 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1229}
1230
1231llvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
1232 llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
1233 llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
1234
1235 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1236}
1237
1238llvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
1239 llvm::Value* cmp_lt) {
1240
1241 llvm::Constant* zero = irb_.getJInt(0);
1242 llvm::Constant* pos1 = irb_.getJInt(1);
1243 llvm::Constant* neg1 = irb_.getJInt(-1);
1244
1245 llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
1246 llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
1247
1248 return result_eq;
1249}
1250
Logan Chien75e4b602012-07-23 14:24:12 -07001251llvm::Value* GBCExpanderPass::Expand_IntegerShift(llvm::Value* src1_value,
1252 llvm::Value* src2_value,
1253 IntegerShiftKind kind,
1254 JType op_jty) {
1255 DCHECK(op_jty == kInt || op_jty == kLong);
1256
1257 // Mask and zero-extend RHS properly
1258 if (op_jty == kInt) {
1259 src2_value = irb_.CreateAnd(src2_value, 0x1f);
1260 } else {
1261 llvm::Value* masked_src2_value = irb_.CreateAnd(src2_value, 0x3f);
1262 src2_value = irb_.CreateZExt(masked_src2_value, irb_.getJLongTy());
1263 }
1264
1265 // Create integer shift llvm instruction
1266 switch (kind) {
1267 case kIntegerSHL:
1268 return irb_.CreateShl(src1_value, src2_value);
1269
1270 case kIntegerSHR:
1271 return irb_.CreateAShr(src1_value, src2_value);
1272
1273 case kIntegerUSHR:
1274 return irb_.CreateLShr(src1_value, src2_value);
1275
1276 default:
1277 LOG(FATAL) << "Unknown integer shift kind: " << kind;
1278 return NULL;
1279 }
1280}
1281
TDYa1275a26d442012-07-26 18:58:38 -07001282llvm::Value* GBCExpanderPass::Expand_HLArrayGet(llvm::CallInst& call_inst,
1283 JType elem_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001284 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1285 llvm::Value* array_addr = call_inst.getArgOperand(1);
1286 llvm::Value* index_value = call_inst.getArgOperand(2);
TDYa127920be7c2012-09-10 17:13:22 -07001287 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275a26d442012-07-26 18:58:38 -07001288
TDYa127920be7c2012-09-10 17:13:22 -07001289 if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1290 EmitGuard_NullPointerException(dex_pc, array_addr);
1291 }
1292 if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) {
1293 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value);
1294 }
TDYa1275a26d442012-07-26 18:58:38 -07001295
1296 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1297
1298 llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
1299
1300 switch (elem_jty) {
1301 case kVoid:
1302 break;
1303
1304 case kBoolean:
1305 case kChar:
1306 array_elem_value = irb_.CreateZExt(array_elem_value, irb_.getJType(elem_jty, kReg));
1307 break;
1308
1309 case kByte:
1310 case kShort:
1311 array_elem_value = irb_.CreateSExt(array_elem_value, irb_.getJType(elem_jty, kReg));
1312 break;
1313
1314 case kInt:
1315 case kLong:
1316 case kFloat:
1317 case kDouble:
1318 case kObject:
1319 break;
1320
1321 default:
1322 LOG(FATAL) << "Unknown java type: " << elem_jty;
1323 }
1324
1325 return array_elem_value;
1326}
1327
1328
1329void GBCExpanderPass::Expand_HLArrayPut(llvm::CallInst& call_inst,
1330 JType elem_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001331 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1332 llvm::Value* new_value = call_inst.getArgOperand(1);
1333 llvm::Value* array_addr = call_inst.getArgOperand(2);
1334 llvm::Value* index_value = call_inst.getArgOperand(3);
TDYa127920be7c2012-09-10 17:13:22 -07001335 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275a26d442012-07-26 18:58:38 -07001336
TDYa127920be7c2012-09-10 17:13:22 -07001337 if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1338 EmitGuard_NullPointerException(dex_pc, array_addr);
1339 }
1340 if (!(opt_flags & MIR_IGNORE_RANGE_CHECK)) {
1341 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value);
1342 }
TDYa1275a26d442012-07-26 18:58:38 -07001343
1344 switch (elem_jty) {
1345 case kVoid:
1346 break;
1347
1348 case kBoolean:
1349 case kChar:
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001350 case kByte:
1351 case kShort:
TDYa1275a26d442012-07-26 18:58:38 -07001352 new_value = irb_.CreateTrunc(new_value, irb_.getJType(elem_jty, kArray));
1353 break;
1354
1355 case kInt:
1356 case kLong:
1357 case kFloat:
1358 case kDouble:
1359 case kObject:
1360 break;
1361
1362 default:
1363 LOG(FATAL) << "Unknown java type: " << elem_jty;
1364 }
1365
1366 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1367
1368 if (elem_jty == kObject) { // If put an object, check the type, and mark GC card table.
1369 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::CheckPutArrayElement);
1370
1371 irb_.CreateCall2(runtime_func, new_value, array_addr);
1372
1373 EmitGuard_ExceptionLandingPad(dex_pc);
1374
1375 EmitMarkGCCard(new_value, array_addr);
1376 }
1377
1378 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
1379
1380 return;
1381}
1382
TDYa1275e869b62012-07-25 00:45:39 -07001383llvm::Value* GBCExpanderPass::Expand_HLIGet(llvm::CallInst& call_inst,
1384 JType field_jty) {
TDYa1275e869b62012-07-25 00:45:39 -07001385 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1386 llvm::Value* object_addr = call_inst.getArgOperand(1);
1387 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(2));
TDYa127920be7c2012-09-10 17:13:22 -07001388 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275e869b62012-07-25 00:45:39 -07001389
TDYa127920be7c2012-09-10 17:13:22 -07001390 if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1391 EmitGuard_NullPointerException(dex_pc, object_addr);
1392 }
TDYa1275e869b62012-07-25 00:45:39 -07001393
1394 llvm::Value* field_value;
1395
1396 int field_offset;
1397 bool is_volatile;
1398 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1399 field_idx, oat_compilation_unit_, field_offset, is_volatile, false);
1400
1401 if (!is_fast_path) {
1402 llvm::Function* runtime_func;
1403
1404 if (field_jty == kObject) {
1405 runtime_func = irb_.GetRuntime(runtime_support::GetObjectInstance);
1406 } else if (field_jty == kLong || field_jty == kDouble) {
1407 runtime_func = irb_.GetRuntime(runtime_support::Get64Instance);
1408 } else {
1409 runtime_func = irb_.GetRuntime(runtime_support::Get32Instance);
1410 }
1411
1412 llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
1413
1414 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1415
1416 EmitUpdateDexPC(dex_pc);
1417
1418 field_value = irb_.CreateCall3(runtime_func, field_idx_value,
1419 method_object_addr, object_addr);
1420
1421 EmitGuard_ExceptionLandingPad(dex_pc);
1422
1423 } else {
1424 DCHECK_GE(field_offset, 0);
1425
1426 llvm::PointerType* field_type =
1427 irb_.getJType(field_jty, kField)->getPointerTo();
1428
1429 llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
1430
1431 llvm::Value* field_addr =
1432 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1433
1434 // TODO: Check is_volatile. We need to generate atomic load instruction
1435 // when is_volatile is true.
1436 field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
1437 }
1438
1439 if (field_jty == kFloat || field_jty == kDouble) {
TDYa1275a26d442012-07-26 18:58:38 -07001440 field_value = irb_.CreateBitCast(field_value, irb_.getJType(field_jty, kAccurate));
TDYa1275e869b62012-07-25 00:45:39 -07001441 }
1442
1443 return field_value;
1444}
1445
1446void GBCExpanderPass::Expand_HLIPut(llvm::CallInst& call_inst,
1447 JType field_jty) {
TDYa1275e869b62012-07-25 00:45:39 -07001448 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001449 llvm::Value* new_value = call_inst.getArgOperand(1);
1450 llvm::Value* object_addr = call_inst.getArgOperand(2);
TDYa1275e869b62012-07-25 00:45:39 -07001451 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(3));
TDYa127920be7c2012-09-10 17:13:22 -07001452 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa1275e869b62012-07-25 00:45:39 -07001453
1454 if (field_jty == kFloat || field_jty == kDouble) {
TDYa1275a26d442012-07-26 18:58:38 -07001455 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty, kField));
TDYa1275e869b62012-07-25 00:45:39 -07001456 }
1457
TDYa127920be7c2012-09-10 17:13:22 -07001458 if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1459 EmitGuard_NullPointerException(dex_pc, object_addr);
1460 }
TDYa1275e869b62012-07-25 00:45:39 -07001461
1462 int field_offset;
1463 bool is_volatile;
1464 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1465 field_idx, oat_compilation_unit_, field_offset, is_volatile, true);
1466
1467 if (!is_fast_path) {
1468 llvm::Function* runtime_func;
1469
1470 if (field_jty == kObject) {
1471 runtime_func = irb_.GetRuntime(runtime_support::SetObjectInstance);
1472 } else if (field_jty == kLong || field_jty == kDouble) {
1473 runtime_func = irb_.GetRuntime(runtime_support::Set64Instance);
1474 } else {
1475 runtime_func = irb_.GetRuntime(runtime_support::Set32Instance);
1476 }
1477
1478 llvm::Value* field_idx_value = irb_.getInt32(field_idx);
1479
1480 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1481
1482 EmitUpdateDexPC(dex_pc);
1483
1484 irb_.CreateCall4(runtime_func, field_idx_value,
1485 method_object_addr, object_addr, new_value);
1486
1487 EmitGuard_ExceptionLandingPad(dex_pc);
1488
1489 } else {
1490 DCHECK_GE(field_offset, 0);
1491
1492 llvm::PointerType* field_type =
1493 irb_.getJType(field_jty, kField)->getPointerTo();
1494
1495 llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
1496
1497 llvm::Value* field_addr =
1498 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1499
1500 // TODO: Check is_volatile. We need to generate atomic store instruction
1501 // when is_volatile is true.
1502 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
1503
1504 if (field_jty == kObject) { // If put an object, mark the GC card table.
1505 EmitMarkGCCard(new_value, object_addr);
1506 }
1507 }
1508
1509 return;
1510}
1511
TDYa127f71bf5a2012-07-29 20:09:52 -07001512llvm::Value* GBCExpanderPass::EmitLoadConstantClass(uint32_t dex_pc,
1513 uint32_t type_idx) {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001514 if (!compiler_->CanAccessTypeWithoutChecks(method_idx_, *dex_file_, type_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001515 llvm::Value* type_idx_value = irb_.getInt32(type_idx);
1516
1517 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1518
1519 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1520
1521 llvm::Function* runtime_func =
1522 irb_.GetRuntime(runtime_support::InitializeTypeAndVerifyAccess);
1523
1524 EmitUpdateDexPC(dex_pc);
1525
1526 llvm::Value* type_object_addr =
1527 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1528
1529 EmitGuard_ExceptionLandingPad(dex_pc);
1530
1531 return type_object_addr;
1532
1533 } else {
1534 // Try to load the class (type) object from the test cache.
1535 llvm::Value* type_field_addr =
1536 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
1537
TDYa127ce4cc0d2012-11-18 16:59:53 -08001538 llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
TDYa127f71bf5a2012-07-29 20:09:52 -07001539
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001540 if (compiler_->CanAssumeTypeIsPresentInDexCache(*dex_file_, type_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001541 return type_object_addr;
1542 }
1543
1544 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1545
1546 // Test whether class (type) object is in the dex cache or not
1547 llvm::Value* equal_null =
1548 irb_.CreateICmpEQ(type_object_addr, irb_.getJNull());
1549
1550 llvm::BasicBlock* block_cont =
1551 CreateBasicBlockWithDexPC(dex_pc, "cont");
1552
1553 llvm::BasicBlock* block_load_class =
1554 CreateBasicBlockWithDexPC(dex_pc, "load_class");
1555
1556 irb_.CreateCondBr(equal_null, block_load_class, block_cont, kUnlikely);
1557
1558 // Failback routine to load the class object
1559 irb_.SetInsertPoint(block_load_class);
1560
1561 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeType);
1562
1563 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1564
1565 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1566
1567 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1568
1569 EmitUpdateDexPC(dex_pc);
1570
1571 llvm::Value* loaded_type_object_addr =
1572 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1573
1574 EmitGuard_ExceptionLandingPad(dex_pc);
1575
1576 llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
1577
1578 irb_.CreateBr(block_cont);
1579
1580 // Now the class object must be loaded
1581 irb_.SetInsertPoint(block_cont);
1582
1583 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1584
1585 phi->addIncoming(type_object_addr, block_original);
1586 phi->addIncoming(loaded_type_object_addr, block_after_load_class);
1587
1588 return phi;
1589 }
1590}
1591
TDYa1275a26d442012-07-26 18:58:38 -07001592llvm::Value* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc,
1593 uint32_t type_idx) {
1594 llvm::BasicBlock* block_load_static =
1595 CreateBasicBlockWithDexPC(dex_pc, "load_static");
1596
1597 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
1598
1599 // Load static storage from dex cache
1600 llvm::Value* storage_field_addr =
1601 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
1602
TDYa127ce4cc0d2012-11-18 16:59:53 -08001603 llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
TDYa1275a26d442012-07-26 18:58:38 -07001604
1605 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1606
1607 // Test: Is the static storage of this class initialized?
1608 llvm::Value* equal_null =
1609 irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
1610
1611 irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely);
1612
1613 // Failback routine to load the class object
1614 irb_.SetInsertPoint(block_load_static);
1615
1616 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeStaticStorage);
1617
1618 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1619
1620 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1621
1622 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1623
1624 EmitUpdateDexPC(dex_pc);
1625
1626 llvm::Value* loaded_storage_object_addr =
1627 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1628
1629 EmitGuard_ExceptionLandingPad(dex_pc);
1630
1631 llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
1632
1633 irb_.CreateBr(block_cont);
1634
1635 // Now the class object must be loaded
1636 irb_.SetInsertPoint(block_cont);
1637
1638 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1639
1640 phi->addIncoming(storage_object_addr, block_original);
1641 phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
1642
1643 return phi;
1644}
1645
1646llvm::Value* GBCExpanderPass::Expand_HLSget(llvm::CallInst& call_inst,
1647 JType field_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001648 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1649 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1650
1651 int field_offset;
1652 int ssb_index;
1653 bool is_referrers_class;
1654 bool is_volatile;
1655
1656 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
1657 field_idx, oat_compilation_unit_, field_offset, ssb_index,
1658 is_referrers_class, is_volatile, false);
1659
1660 llvm::Value* static_field_value;
1661
1662 if (!is_fast_path) {
1663 llvm::Function* runtime_func;
1664
1665 if (field_jty == kObject) {
1666 runtime_func = irb_.GetRuntime(runtime_support::GetObjectStatic);
1667 } else if (field_jty == kLong || field_jty == kDouble) {
1668 runtime_func = irb_.GetRuntime(runtime_support::Get64Static);
1669 } else {
1670 runtime_func = irb_.GetRuntime(runtime_support::Get32Static);
1671 }
1672
1673 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1674
1675 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1676
1677 EmitUpdateDexPC(dex_pc);
1678
1679 static_field_value =
1680 irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
1681
1682 EmitGuard_ExceptionLandingPad(dex_pc);
1683
1684 } else {
1685 DCHECK_GE(field_offset, 0);
1686
1687 llvm::Value* static_storage_addr = NULL;
1688
1689 if (is_referrers_class) {
1690 // Fast path, static storage base is this method's class
1691 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1692
1693 static_storage_addr =
1694 irb_.LoadFromObjectOffset(method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001695 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
TDYa1275a26d442012-07-26 18:58:38 -07001696 irb_.getJObjectTy(),
1697 kTBAAConstJObject);
1698 } else {
1699 // Medium path, static storage base in a different class which
1700 // requires checks that the other class is initialized
1701 DCHECK_GE(ssb_index, 0);
1702 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1703 }
1704
1705 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1706
1707 llvm::Value* static_field_addr =
1708 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
1709 irb_.getJType(field_jty, kField)->getPointerTo());
1710
1711 // TODO: Check is_volatile. We need to generate atomic load instruction
1712 // when is_volatile is true.
1713 static_field_value = irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
1714 }
1715
1716 if (field_jty == kFloat || field_jty == kDouble) {
1717 static_field_value =
1718 irb_.CreateBitCast(static_field_value, irb_.getJType(field_jty, kAccurate));
1719 }
1720
1721 return static_field_value;
1722}
1723
1724void GBCExpanderPass::Expand_HLSput(llvm::CallInst& call_inst,
1725 JType field_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001726 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1727 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1728 llvm::Value* new_value = call_inst.getArgOperand(1);
1729
1730 if (field_jty == kFloat || field_jty == kDouble) {
1731 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty, kField));
1732 }
1733
1734 int field_offset;
1735 int ssb_index;
1736 bool is_referrers_class;
1737 bool is_volatile;
1738
1739 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
1740 field_idx, oat_compilation_unit_, field_offset, ssb_index,
1741 is_referrers_class, is_volatile, true);
1742
1743 if (!is_fast_path) {
1744 llvm::Function* runtime_func;
1745
1746 if (field_jty == kObject) {
1747 runtime_func = irb_.GetRuntime(runtime_support::SetObjectStatic);
1748 } else if (field_jty == kLong || field_jty == kDouble) {
1749 runtime_func = irb_.GetRuntime(runtime_support::Set64Static);
1750 } else {
1751 runtime_func = irb_.GetRuntime(runtime_support::Set32Static);
1752 }
1753
1754 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1755
1756 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1757
1758 EmitUpdateDexPC(dex_pc);
1759
1760 irb_.CreateCall3(runtime_func, field_idx_value,
1761 method_object_addr, new_value);
1762
1763 EmitGuard_ExceptionLandingPad(dex_pc);
1764
1765 } else {
1766 DCHECK_GE(field_offset, 0);
1767
1768 llvm::Value* static_storage_addr = NULL;
1769
1770 if (is_referrers_class) {
1771 // Fast path, static storage base is this method's class
1772 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1773
1774 static_storage_addr =
1775 irb_.LoadFromObjectOffset(method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08001776 art::mirror::AbstractMethod::DeclaringClassOffset().Int32Value(),
TDYa1275a26d442012-07-26 18:58:38 -07001777 irb_.getJObjectTy(),
1778 kTBAAConstJObject);
1779 } else {
1780 // Medium path, static storage base in a different class which
1781 // requires checks that the other class is initialized
1782 DCHECK_GE(ssb_index, 0);
1783 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1784 }
1785
1786 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1787
1788 llvm::Value* static_field_addr =
1789 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
1790 irb_.getJType(field_jty, kField)->getPointerTo());
1791
1792 // TODO: Check is_volatile. We need to generate atomic store instruction
1793 // when is_volatile is true.
1794 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
1795
1796 if (field_jty == kObject) { // If put an object, mark the GC card table.
1797 EmitMarkGCCard(new_value, static_storage_addr);
1798 }
1799 }
1800
1801 return;
1802}
1803
TDYa127f71bf5a2012-07-29 20:09:52 -07001804llvm::Value* GBCExpanderPass::Expand_ConstString(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001805 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1806 uint32_t string_idx = LV2UInt(call_inst.getArgOperand(0));
1807
1808 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
1809
TDYa127ce4cc0d2012-11-18 16:59:53 -08001810 llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
TDYa127f71bf5a2012-07-29 20:09:52 -07001811
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001812 if (!compiler_->CanAssumeStringIsPresentInDexCache(*dex_file_, string_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001813 llvm::BasicBlock* block_str_exist =
1814 CreateBasicBlockWithDexPC(dex_pc, "str_exist");
1815
1816 llvm::BasicBlock* block_str_resolve =
1817 CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
1818
1819 llvm::BasicBlock* block_cont =
1820 CreateBasicBlockWithDexPC(dex_pc, "str_cont");
1821
1822 // Test: Is the string resolved and in the dex cache?
1823 llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.getJNull());
1824
1825 irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist, kUnlikely);
1826
1827 // String is resolved, go to next basic block.
1828 irb_.SetInsertPoint(block_str_exist);
1829 irb_.CreateBr(block_cont);
1830
1831 // String is not resolved yet, resolve it now.
1832 irb_.SetInsertPoint(block_str_resolve);
1833
1834 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::ResolveString);
1835
1836 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1837
1838 llvm::Value* string_idx_value = irb_.getInt32(string_idx);
1839
1840 EmitUpdateDexPC(dex_pc);
1841
1842 llvm::Value* result = irb_.CreateCall2(runtime_func, method_object_addr,
1843 string_idx_value);
1844
1845 EmitGuard_ExceptionLandingPad(dex_pc);
1846
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07001847 irb_.CreateBr(block_cont);
1848
1849
TDYa127f71bf5a2012-07-29 20:09:52 -07001850 llvm::BasicBlock* block_pre_cont = irb_.GetInsertBlock();
1851
1852 irb_.SetInsertPoint(block_cont);
1853
1854 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1855
1856 phi->addIncoming(string_addr, block_str_exist);
1857 phi->addIncoming(result, block_pre_cont);
1858
1859 string_addr = phi;
1860 }
1861
1862 return string_addr;
1863}
1864
1865llvm::Value* GBCExpanderPass::Expand_ConstClass(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001866 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1867 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1868
1869 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
1870
1871 return type_object_addr;
1872}
1873
1874void GBCExpanderPass::Expand_MonitorEnter(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001875 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1876 llvm::Value* object_addr = call_inst.getArgOperand(1);
TDYa127920be7c2012-09-10 17:13:22 -07001877 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa127f71bf5a2012-07-29 20:09:52 -07001878
TDYa127920be7c2012-09-10 17:13:22 -07001879 if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1880 EmitGuard_NullPointerException(dex_pc, object_addr);
1881 }
TDYa127f71bf5a2012-07-29 20:09:52 -07001882
TDYa127ce4cc0d2012-11-18 16:59:53 -08001883 EmitUpdateDexPC(dex_pc);
1884
TDYa127f71bf5a2012-07-29 20:09:52 -07001885 irb_.Runtime().EmitLockObject(object_addr);
1886
1887 return;
1888}
1889
1890void GBCExpanderPass::Expand_MonitorExit(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001891 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1892 llvm::Value* object_addr = call_inst.getArgOperand(1);
TDYa127920be7c2012-09-10 17:13:22 -07001893 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa127f71bf5a2012-07-29 20:09:52 -07001894
TDYa127920be7c2012-09-10 17:13:22 -07001895 if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
1896 EmitGuard_NullPointerException(dex_pc, object_addr);
1897 }
TDYa127f71bf5a2012-07-29 20:09:52 -07001898
1899 EmitUpdateDexPC(dex_pc);
1900
1901 irb_.Runtime().EmitUnlockObject(object_addr);
1902
1903 EmitGuard_ExceptionLandingPad(dex_pc);
1904
1905 return;
1906}
1907
1908void GBCExpanderPass::Expand_HLCheckCast(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001909 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1910 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1911 llvm::Value* object_addr = call_inst.getArgOperand(1);
1912
1913 llvm::BasicBlock* block_test_class =
1914 CreateBasicBlockWithDexPC(dex_pc, "test_class");
1915
1916 llvm::BasicBlock* block_test_sub_class =
1917 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
1918
1919 llvm::BasicBlock* block_cont =
1920 CreateBasicBlockWithDexPC(dex_pc, "checkcast_cont");
1921
1922 // Test: Is the reference equal to null? Act as no-op when it is null.
1923 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
1924
1925 irb_.CreateCondBr(equal_null,
1926 block_cont,
1927 block_test_class);
1928
1929 // Test: Is the object instantiated from the given class?
1930 irb_.SetInsertPoint(block_test_class);
1931 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
Ian Rogers98573f92013-01-30 17:26:32 -08001932 DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
TDYa127f71bf5a2012-07-29 20:09:52 -07001933
1934 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
1935
1936 llvm::Value* object_type_field_addr =
1937 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
1938
1939 llvm::Value* object_type_object_addr =
1940 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
1941
1942 llvm::Value* equal_class =
1943 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
1944
1945 irb_.CreateCondBr(equal_class,
1946 block_cont,
1947 block_test_sub_class);
1948
1949 // Test: Is the object instantiated from the subclass of the given class?
1950 irb_.SetInsertPoint(block_test_sub_class);
1951
1952 EmitUpdateDexPC(dex_pc);
1953
1954 irb_.CreateCall2(irb_.GetRuntime(runtime_support::CheckCast),
1955 type_object_addr, object_type_object_addr);
1956
1957 EmitGuard_ExceptionLandingPad(dex_pc);
1958
1959 irb_.CreateBr(block_cont);
1960
1961 irb_.SetInsertPoint(block_cont);
1962
1963 return;
1964}
1965
1966llvm::Value* GBCExpanderPass::Expand_InstanceOf(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001967 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1968 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1969 llvm::Value* object_addr = call_inst.getArgOperand(1);
1970
1971 llvm::BasicBlock* block_nullp =
1972 CreateBasicBlockWithDexPC(dex_pc, "nullp");
1973
1974 llvm::BasicBlock* block_test_class =
1975 CreateBasicBlockWithDexPC(dex_pc, "test_class");
1976
1977 llvm::BasicBlock* block_class_equals =
1978 CreateBasicBlockWithDexPC(dex_pc, "class_eq");
1979
1980 llvm::BasicBlock* block_test_sub_class =
1981 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
1982
1983 llvm::BasicBlock* block_cont =
1984 CreateBasicBlockWithDexPC(dex_pc, "instance_of_cont");
1985
1986 // Overview of the following code :
1987 // We check for null, if so, then false, otherwise check for class == . If so
1988 // then true, otherwise do callout slowpath.
1989 //
1990 // Test: Is the reference equal to null? Set 0 when it is null.
1991 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
1992
1993 irb_.CreateCondBr(equal_null, block_nullp, block_test_class);
1994
1995 irb_.SetInsertPoint(block_nullp);
1996 irb_.CreateBr(block_cont);
1997
1998 // Test: Is the object instantiated from the given class?
1999 irb_.SetInsertPoint(block_test_class);
2000 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
Ian Rogers98573f92013-01-30 17:26:32 -08002001 DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
TDYa127f71bf5a2012-07-29 20:09:52 -07002002
2003 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
2004
2005 llvm::Value* object_type_field_addr =
2006 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
2007
2008 llvm::Value* object_type_object_addr =
2009 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
2010
2011 llvm::Value* equal_class =
2012 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
2013
2014 irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class);
2015
2016 irb_.SetInsertPoint(block_class_equals);
2017 irb_.CreateBr(block_cont);
2018
2019 // Test: Is the object instantiated from the subclass of the given class?
2020 irb_.SetInsertPoint(block_test_sub_class);
2021 llvm::Value* result =
2022 irb_.CreateCall2(irb_.GetRuntime(runtime_support::IsAssignable),
2023 type_object_addr, object_type_object_addr);
2024 irb_.CreateBr(block_cont);
2025
2026 irb_.SetInsertPoint(block_cont);
2027
2028 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJIntTy(), 3);
2029
2030 phi->addIncoming(irb_.getJInt(0), block_nullp);
2031 phi->addIncoming(irb_.getJInt(1), block_class_equals);
2032 phi->addIncoming(result, block_test_sub_class);
2033
2034 return phi;
2035}
2036
2037llvm::Value* GBCExpanderPass::Expand_NewInstance(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002038 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2039 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2040
2041 llvm::Function* runtime_func;
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002042 if (compiler_->CanAccessInstantiableTypeWithoutChecks(method_idx_, *dex_file_, type_idx)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002043 runtime_func = irb_.GetRuntime(runtime_support::AllocObject);
2044 } else {
2045 runtime_func = irb_.GetRuntime(runtime_support::AllocObjectWithAccessCheck);
2046 }
2047
2048 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2049
2050 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2051
2052 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2053
2054 EmitUpdateDexPC(dex_pc);
2055
2056 llvm::Value* object_addr =
2057 irb_.CreateCall3(runtime_func, type_index_value, method_object_addr, thread_object_addr);
2058
2059 EmitGuard_ExceptionLandingPad(dex_pc);
2060
2061 return object_addr;
2062}
2063
2064llvm::Value* GBCExpanderPass::Expand_HLInvoke(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002065 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
TDYa127920be7c2012-09-10 17:13:22 -07002066 art::InvokeType invoke_type = static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
2067 bool is_static = (invoke_type == art::kStatic);
TDYa127f71bf5a2012-07-29 20:09:52 -07002068 uint32_t callee_method_idx = LV2UInt(call_inst.getArgOperand(1));
TDYa127920be7c2012-09-10 17:13:22 -07002069 int opt_flags = LV2UInt(call_inst.getArgOperand(2));
TDYa127f71bf5a2012-07-29 20:09:52 -07002070
2071 // Compute invoke related information for compiler decision
2072 int vtable_idx = -1;
2073 uintptr_t direct_code = 0;
2074 uintptr_t direct_method = 0;
2075 bool is_fast_path = compiler_->
2076 ComputeInvokeInfo(callee_method_idx, oat_compilation_unit_,
2077 invoke_type, vtable_idx, direct_code, direct_method);
2078
2079 // Load *this* actual parameter
2080 llvm::Value* this_addr = NULL;
2081
2082 if (!is_static) {
2083 // Test: Is *this* parameter equal to null?
2084 this_addr = call_inst.getArgOperand(3);
2085 }
2086
2087 // Load the method object
2088 llvm::Value* callee_method_object_addr = NULL;
2089
2090 if (!is_fast_path) {
2091 callee_method_object_addr =
2092 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx, invoke_type,
2093 this_addr, dex_pc, is_fast_path);
2094
TDYa127920be7c2012-09-10 17:13:22 -07002095 if (!is_static && !(opt_flags & MIR_IGNORE_NULL_CHECK)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002096 EmitGuard_NullPointerException(dex_pc, this_addr);
2097 }
2098 } else {
TDYa127920be7c2012-09-10 17:13:22 -07002099 if (!is_static && !(opt_flags & MIR_IGNORE_NULL_CHECK)) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002100 EmitGuard_NullPointerException(dex_pc, this_addr);
2101 }
2102
2103 switch (invoke_type) {
TDYa127920be7c2012-09-10 17:13:22 -07002104 case art::kStatic:
2105 case art::kDirect:
TDYa127f71bf5a2012-07-29 20:09:52 -07002106 if (direct_method != 0u &&
2107 direct_method != static_cast<uintptr_t>(-1)) {
2108 callee_method_object_addr =
2109 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_method),
2110 irb_.getJObjectTy());
2111 } else {
2112 callee_method_object_addr =
2113 EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
2114 }
2115 break;
2116
TDYa127920be7c2012-09-10 17:13:22 -07002117 case art::kVirtual:
TDYa127f71bf5a2012-07-29 20:09:52 -07002118 DCHECK(vtable_idx != -1);
2119 callee_method_object_addr =
2120 EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
2121 break;
2122
TDYa127920be7c2012-09-10 17:13:22 -07002123 case art::kSuper:
TDYa127f71bf5a2012-07-29 20:09:52 -07002124 LOG(FATAL) << "invoke-super should be promoted to invoke-direct in "
2125 "the fast path.";
2126 break;
2127
TDYa127920be7c2012-09-10 17:13:22 -07002128 case art::kInterface:
TDYa127f71bf5a2012-07-29 20:09:52 -07002129 callee_method_object_addr =
2130 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx,
2131 invoke_type, this_addr,
2132 dex_pc, is_fast_path);
2133 break;
2134 }
2135 }
2136
2137 // Load the actual parameter
2138 std::vector<llvm::Value*> args;
2139
2140 args.push_back(callee_method_object_addr); // method object for callee
2141
2142 for (uint32_t i = 3; i < call_inst.getNumArgOperands(); ++i) {
2143 args.push_back(call_inst.getArgOperand(i));
2144 }
2145
2146 llvm::Value* code_addr;
2147 if (direct_code != 0u &&
2148 direct_code != static_cast<uintptr_t>(-1)) {
2149 code_addr =
2150 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_code),
2151 GetFunctionType(callee_method_idx, is_static)->getPointerTo());
2152 } else {
2153 code_addr =
2154 irb_.LoadFromObjectOffset(callee_method_object_addr,
Ian Rogers98573f92013-01-30 17:26:32 -08002155 art::mirror::AbstractMethod::GetCodeOffset().Int32Value(),
TDYa127f71bf5a2012-07-29 20:09:52 -07002156 GetFunctionType(callee_method_idx, is_static)->getPointerTo(),
TDYa127ce4cc0d2012-11-18 16:59:53 -08002157 kTBAARuntimeInfo);
TDYa127f71bf5a2012-07-29 20:09:52 -07002158 }
2159
2160 // Invoke callee
2161 EmitUpdateDexPC(dex_pc);
2162 llvm::Value* retval = irb_.CreateCall(code_addr, args);
2163 EmitGuard_ExceptionLandingPad(dex_pc);
2164
2165 return retval;
2166}
2167
2168llvm::Value* GBCExpanderPass::Expand_OptArrayLength(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002169 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2170 // Get the array object address
2171 llvm::Value* array_addr = call_inst.getArgOperand(1);
TDYa127920be7c2012-09-10 17:13:22 -07002172 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
TDYa127f71bf5a2012-07-29 20:09:52 -07002173
TDYa127920be7c2012-09-10 17:13:22 -07002174 if (!(opt_flags & MIR_IGNORE_NULL_CHECK)) {
2175 EmitGuard_NullPointerException(dex_pc, array_addr);
2176 }
TDYa127f71bf5a2012-07-29 20:09:52 -07002177
2178 // Get the array length and store it to the register
2179 return EmitLoadArrayLength(array_addr);
2180}
2181
2182llvm::Value* GBCExpanderPass::Expand_NewArray(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002183 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2184 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2185 llvm::Value* length = call_inst.getArgOperand(1);
2186
2187 return EmitAllocNewArray(dex_pc, length, type_idx, false);
2188}
2189
2190llvm::Value* GBCExpanderPass::Expand_HLFilledNewArray(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002191 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2192 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(1));
2193 uint32_t length = call_inst.getNumArgOperands() - 3;
2194
2195 llvm::Value* object_addr =
2196 EmitAllocNewArray(dex_pc, irb_.getInt32(length), type_idx, true);
2197
2198 if (length > 0) {
2199 // Check for the element type
2200 uint32_t type_desc_len = 0;
2201 const char* type_desc =
2202 dex_file_->StringByTypeIdx(type_idx, &type_desc_len);
2203
2204 DCHECK_GE(type_desc_len, 2u); // should be guaranteed by verifier
2205 DCHECK_EQ(type_desc[0], '['); // should be guaranteed by verifier
2206 bool is_elem_int_ty = (type_desc[1] == 'I');
2207
2208 uint32_t alignment;
2209 llvm::Constant* elem_size;
2210 llvm::PointerType* field_type;
2211
2212 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
2213 // as the element, thus we are only checking 2 cases: primitive int and
2214 // non-primitive type.
2215 if (is_elem_int_ty) {
2216 alignment = sizeof(int32_t);
2217 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
2218 field_type = irb_.getJIntTy()->getPointerTo();
2219 } else {
2220 alignment = irb_.getSizeOfPtrEquivInt();
2221 elem_size = irb_.getSizeOfPtrEquivIntValue();
2222 field_type = irb_.getJObjectTy()->getPointerTo();
2223 }
2224
2225 llvm::Value* data_field_offset =
Ian Rogers98573f92013-01-30 17:26:32 -08002226 irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
TDYa127f71bf5a2012-07-29 20:09:52 -07002227
2228 llvm::Value* data_field_addr =
2229 irb_.CreatePtrDisp(object_addr, data_field_offset, field_type);
2230
2231 // TODO: Tune this code. Currently we are generating one instruction for
2232 // one element which may be very space consuming. Maybe changing to use
2233 // memcpy may help; however, since we can't guarantee that the alloca of
2234 // dalvik register are continuous, we can't perform such optimization yet.
2235 for (uint32_t i = 0; i < length; ++i) {
2236 llvm::Value* reg_value = call_inst.getArgOperand(i+3);
2237
2238 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
2239
2240 data_field_addr =
2241 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
2242 }
2243 }
2244
2245 return object_addr;
2246}
2247
2248void GBCExpanderPass::Expand_HLFillArrayData(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002249 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2250 int32_t payload_offset = static_cast<int32_t>(dex_pc) +
2251 LV2SInt(call_inst.getArgOperand(0));
2252 llvm::Value* array_addr = call_inst.getArgOperand(1);
2253
TDYa127920be7c2012-09-10 17:13:22 -07002254 const art::Instruction::ArrayDataPayload* payload =
2255 reinterpret_cast<const art::Instruction::ArrayDataPayload*>(
TDYa127f71bf5a2012-07-29 20:09:52 -07002256 code_item_->insns_ + payload_offset);
2257
2258 if (payload->element_count == 0) {
2259 // When the number of the elements in the payload is zero, we don't have
2260 // to copy any numbers. However, we should check whether the array object
2261 // address is equal to null or not.
2262 EmitGuard_NullPointerException(dex_pc, array_addr);
2263 } else {
2264 // To save the code size, we are going to call the runtime function to
2265 // copy the content from DexFile.
2266
2267 // NOTE: We will check for the NullPointerException in the runtime.
2268
2269 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::FillArrayData);
2270
2271 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2272
2273 EmitUpdateDexPC(dex_pc);
2274
2275 irb_.CreateCall4(runtime_func,
2276 method_object_addr, irb_.getInt32(dex_pc),
2277 array_addr, irb_.getInt32(payload_offset));
2278
2279 EmitGuard_ExceptionLandingPad(dex_pc);
2280 }
2281
2282 return;
2283}
2284
2285llvm::Value* GBCExpanderPass::EmitAllocNewArray(uint32_t dex_pc,
2286 llvm::Value* array_length_value,
2287 uint32_t type_idx,
2288 bool is_filled_new_array) {
2289 llvm::Function* runtime_func;
2290
2291 bool skip_access_check =
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002292 compiler_->CanAccessTypeWithoutChecks(method_idx_, *dex_file_, type_idx);
TDYa127f71bf5a2012-07-29 20:09:52 -07002293
2294
2295 if (is_filled_new_array) {
2296 runtime_func = skip_access_check ?
2297 irb_.GetRuntime(runtime_support::CheckAndAllocArray) :
2298 irb_.GetRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck);
2299 } else {
2300 runtime_func = skip_access_check ?
2301 irb_.GetRuntime(runtime_support::AllocArray) :
2302 irb_.GetRuntime(runtime_support::AllocArrayWithAccessCheck);
2303 }
2304
2305 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2306
2307 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2308
2309 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2310
2311 EmitUpdateDexPC(dex_pc);
2312
2313 llvm::Value* object_addr =
2314 irb_.CreateCall4(runtime_func, type_index_value, method_object_addr,
2315 array_length_value, thread_object_addr);
2316
2317 EmitGuard_ExceptionLandingPad(dex_pc);
2318
2319 return object_addr;
2320}
2321
2322llvm::Value* GBCExpanderPass::
2323EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
TDYa127920be7c2012-09-10 17:13:22 -07002324 art::InvokeType invoke_type,
TDYa127f71bf5a2012-07-29 20:09:52 -07002325 llvm::Value* this_addr,
2326 uint32_t dex_pc,
2327 bool is_fast_path) {
2328
2329 llvm::Function* runtime_func = NULL;
2330
2331 switch (invoke_type) {
TDYa127920be7c2012-09-10 17:13:22 -07002332 case art::kStatic:
TDYa127f71bf5a2012-07-29 20:09:52 -07002333 runtime_func = irb_.GetRuntime(runtime_support::FindStaticMethodWithAccessCheck);
2334 break;
2335
TDYa127920be7c2012-09-10 17:13:22 -07002336 case art::kDirect:
TDYa127f71bf5a2012-07-29 20:09:52 -07002337 runtime_func = irb_.GetRuntime(runtime_support::FindDirectMethodWithAccessCheck);
2338 break;
2339
TDYa127920be7c2012-09-10 17:13:22 -07002340 case art::kVirtual:
TDYa127f71bf5a2012-07-29 20:09:52 -07002341 runtime_func = irb_.GetRuntime(runtime_support::FindVirtualMethodWithAccessCheck);
2342 break;
2343
TDYa127920be7c2012-09-10 17:13:22 -07002344 case art::kSuper:
TDYa127f71bf5a2012-07-29 20:09:52 -07002345 runtime_func = irb_.GetRuntime(runtime_support::FindSuperMethodWithAccessCheck);
2346 break;
2347
TDYa127920be7c2012-09-10 17:13:22 -07002348 case art::kInterface:
TDYa127f71bf5a2012-07-29 20:09:52 -07002349 if (is_fast_path) {
2350 runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethod);
2351 } else {
2352 runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethodWithAccessCheck);
2353 }
2354 break;
2355 }
2356
2357 llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
2358
2359 if (this_addr == NULL) {
TDYa127920be7c2012-09-10 17:13:22 -07002360 DCHECK_EQ(invoke_type, art::kStatic);
TDYa127f71bf5a2012-07-29 20:09:52 -07002361 this_addr = irb_.getJNull();
2362 }
2363
2364 llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
2365
2366 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2367
2368 EmitUpdateDexPC(dex_pc);
2369
2370 llvm::Value* callee_method_object_addr =
2371 irb_.CreateCall4(runtime_func,
2372 callee_method_idx_value,
2373 this_addr,
2374 caller_method_object_addr,
2375 thread_object_addr);
2376
2377 EmitGuard_ExceptionLandingPad(dex_pc);
2378
2379 return callee_method_object_addr;
2380}
2381
TDYa1275e869b62012-07-25 00:45:39 -07002382void GBCExpanderPass::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
2383 // Using runtime support, let the target can override by InlineAssembly.
2384 irb_.Runtime().EmitMarkGCCard(value, target_addr);
2385}
2386
2387void GBCExpanderPass::EmitUpdateDexPC(uint32_t dex_pc) {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002388 if (shadow_frame_ == NULL) {
2389 return;
2390 }
TDYa1275e869b62012-07-25 00:45:39 -07002391 irb_.StoreToObjectOffset(shadow_frame_,
TDYa127920be7c2012-09-10 17:13:22 -07002392 art::ShadowFrame::DexPCOffset(),
TDYa1275e869b62012-07-25 00:45:39 -07002393 irb_.getInt32(dex_pc),
2394 kTBAAShadowFrame);
2395}
2396
2397void GBCExpanderPass::EmitGuard_DivZeroException(uint32_t dex_pc,
2398 llvm::Value* denominator,
2399 JType op_jty) {
2400 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
2401
2402 llvm::Constant* zero = irb_.getJZero(op_jty);
2403
2404 llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
2405
2406 llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
2407
2408 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
2409
2410 irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
2411
2412 irb_.SetInsertPoint(block_exception);
2413 EmitUpdateDexPC(dex_pc);
2414 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowDivZeroException));
2415 EmitBranchExceptionLandingPad(dex_pc);
2416
2417 irb_.SetInsertPoint(block_continue);
2418}
2419
2420void GBCExpanderPass::EmitGuard_NullPointerException(uint32_t dex_pc,
2421 llvm::Value* object) {
2422 llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
2423
2424 llvm::BasicBlock* block_exception =
2425 CreateBasicBlockWithDexPC(dex_pc, "nullp");
2426
2427 llvm::BasicBlock* block_continue =
2428 CreateBasicBlockWithDexPC(dex_pc, "cont");
2429
2430 irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
2431
2432 irb_.SetInsertPoint(block_exception);
2433 EmitUpdateDexPC(dex_pc);
2434 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowNullPointerException),
2435 irb_.getInt32(dex_pc));
2436 EmitBranchExceptionLandingPad(dex_pc);
2437
2438 irb_.SetInsertPoint(block_continue);
2439}
2440
2441void
2442GBCExpanderPass::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
2443 llvm::Value* array,
2444 llvm::Value* index) {
2445 llvm::Value* array_len = EmitLoadArrayLength(array);
2446
2447 llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
2448
2449 llvm::BasicBlock* block_exception =
2450 CreateBasicBlockWithDexPC(dex_pc, "overflow");
2451
2452 llvm::BasicBlock* block_continue =
2453 CreateBasicBlockWithDexPC(dex_pc, "cont");
2454
2455 irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
2456
2457 irb_.SetInsertPoint(block_exception);
2458
2459 EmitUpdateDexPC(dex_pc);
2460 irb_.CreateCall2(irb_.GetRuntime(runtime_support::ThrowIndexOutOfBounds), index, array_len);
2461 EmitBranchExceptionLandingPad(dex_pc);
2462
2463 irb_.SetInsertPoint(block_continue);
2464}
2465
TDYa1275e869b62012-07-25 00:45:39 -07002466llvm::FunctionType* GBCExpanderPass::GetFunctionType(uint32_t method_idx,
2467 bool is_static) {
2468 // Get method signature
TDYa127920be7c2012-09-10 17:13:22 -07002469 art::DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
TDYa1275e869b62012-07-25 00:45:39 -07002470
2471 uint32_t shorty_size;
2472 const char* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
2473 CHECK_GE(shorty_size, 1u);
2474
2475 // Get return type
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002476
2477 char ret_shorty = shorty[0];
buzbee26f10ee2012-12-21 11:16:29 -08002478 ret_shorty = art::RemapShorty(ret_shorty);
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002479 llvm::Type* ret_type = irb_.getJType(ret_shorty, kAccurate);
TDYa1275e869b62012-07-25 00:45:39 -07002480
2481 // Get argument type
2482 std::vector<llvm::Type*> args_type;
2483
2484 args_type.push_back(irb_.getJObjectTy()); // method object pointer
2485
2486 if (!is_static) {
2487 args_type.push_back(irb_.getJType('L', kAccurate)); // "this" object pointer
2488 }
2489
2490 for (uint32_t i = 1; i < shorty_size; ++i) {
buzbee26f10ee2012-12-21 11:16:29 -08002491 char shorty_type = art::RemapShorty(shorty[i]);
TDYa127f71bf5a2012-07-29 20:09:52 -07002492 args_type.push_back(irb_.getJType(shorty_type, kAccurate));
TDYa1275e869b62012-07-25 00:45:39 -07002493 }
2494
2495 return llvm::FunctionType::get(ret_type, args_type, false);
2496}
2497
2498
2499llvm::BasicBlock* GBCExpanderPass::
2500CreateBasicBlockWithDexPC(uint32_t dex_pc, const char* postfix) {
2501 std::string name;
2502
2503#if !defined(NDEBUG)
TDYa127920be7c2012-09-10 17:13:22 -07002504 art::StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
TDYa1275e869b62012-07-25 00:45:39 -07002505#endif
2506
2507 return llvm::BasicBlock::Create(context_, name, func_);
2508}
2509
2510llvm::BasicBlock* GBCExpanderPass::GetBasicBlock(uint32_t dex_pc) {
2511 DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07002512 CHECK(basic_blocks_[dex_pc] != NULL);
TDYa1275e869b62012-07-25 00:45:39 -07002513 return basic_blocks_[dex_pc];
2514}
2515
2516int32_t GBCExpanderPass::GetTryItemOffset(uint32_t dex_pc) {
2517 int32_t min = 0;
2518 int32_t max = code_item_->tries_size_ - 1;
2519
2520 while (min <= max) {
2521 int32_t mid = min + (max - min) / 2;
2522
TDYa127920be7c2012-09-10 17:13:22 -07002523 const art::DexFile::TryItem* ti = art::DexFile::GetTryItems(*code_item_, mid);
TDYa1275e869b62012-07-25 00:45:39 -07002524 uint32_t start = ti->start_addr_;
2525 uint32_t end = start + ti->insn_count_;
2526
2527 if (dex_pc < start) {
2528 max = mid - 1;
2529 } else if (dex_pc >= end) {
2530 min = mid + 1;
2531 } else {
2532 return mid; // found
2533 }
2534 }
2535
2536 return -1; // not found
2537}
2538
2539llvm::BasicBlock* GBCExpanderPass::GetLandingPadBasicBlock(uint32_t dex_pc) {
2540 // Find the try item for this address in this method
2541 int32_t ti_offset = GetTryItemOffset(dex_pc);
2542
2543 if (ti_offset == -1) {
2544 return NULL; // No landing pad is available for this address.
2545 }
2546
2547 // Check for the existing landing pad basic block
2548 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2549 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
2550
2551 if (block_lpad) {
2552 // We have generated landing pad for this try item already. Return the
2553 // same basic block.
2554 return block_lpad;
2555 }
2556
2557 // Get try item from code item
TDYa127920be7c2012-09-10 17:13:22 -07002558 const art::DexFile::TryItem* ti = art::DexFile::GetTryItems(*code_item_, ti_offset);
TDYa1275e869b62012-07-25 00:45:39 -07002559
2560 std::string lpadname;
2561
2562#if !defined(NDEBUG)
TDYa127920be7c2012-09-10 17:13:22 -07002563 art::StringAppendF(&lpadname, "lpad%d_%04x_to_%04x", ti_offset, ti->start_addr_, ti->handler_off_);
TDYa1275e869b62012-07-25 00:45:39 -07002564#endif
2565
2566 // Create landing pad basic block
2567 block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
2568
2569 // Change IRBuilder insert point
2570 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2571 irb_.SetInsertPoint(block_lpad);
2572
2573 // Find catch block with matching type
2574 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2575
2576 llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
2577
2578 llvm::Value* catch_handler_index_value =
2579 irb_.CreateCall2(irb_.GetRuntime(runtime_support::FindCatchBlock),
2580 method_object_addr, ti_offset_value);
2581
2582 // Switch instruction (Go to unwind basic block by default)
2583 llvm::SwitchInst* sw =
2584 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
2585
2586 // Cases with matched catch block
TDYa127920be7c2012-09-10 17:13:22 -07002587 art::CatchHandlerIterator iter(*code_item_, ti->start_addr_);
TDYa1275e869b62012-07-25 00:45:39 -07002588
2589 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
2590 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
2591 }
2592
2593 // Restore the orignal insert point for IRBuilder
2594 irb_.restoreIP(irb_ip_original);
2595
2596 // Cache this landing pad
2597 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2598 basic_block_landing_pads_[ti_offset] = block_lpad;
2599
2600 return block_lpad;
2601}
2602
2603llvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() {
2604 // Check the existing unwinding baisc block block
2605 if (basic_block_unwind_ != NULL) {
2606 return basic_block_unwind_;
2607 }
2608
2609 // Create new basic block for unwinding
2610 basic_block_unwind_ =
2611 llvm::BasicBlock::Create(context_, "exception_unwind", func_);
2612
2613 // Change IRBuilder insert point
2614 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2615 irb_.SetInsertPoint(basic_block_unwind_);
2616
2617 // Pop the shadow frame
2618 Expand_PopShadowFrame();
2619
2620 // Emit the code to return default value (zero) for the given return type.
2621 char ret_shorty = oat_compilation_unit_->GetShorty()[0];
buzbee26f10ee2012-12-21 11:16:29 -08002622 ret_shorty = art::RemapShorty(ret_shorty);
TDYa1275e869b62012-07-25 00:45:39 -07002623 if (ret_shorty == 'V') {
2624 irb_.CreateRetVoid();
2625 } else {
2626 irb_.CreateRet(irb_.getJZero(ret_shorty));
2627 }
2628
2629 // Restore the orignal insert point for IRBuilder
2630 irb_.restoreIP(irb_ip_original);
2631
2632 return basic_block_unwind_;
2633}
2634
2635void GBCExpanderPass::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
2636 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
TDYa12755e5e6c2012-09-11 15:14:42 -07002637 landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
TDYa127aa558872012-08-16 05:11:07 -07002638 irb_.GetInsertBlock()));
TDYa1275e869b62012-07-25 00:45:39 -07002639 irb_.CreateBr(lpad);
2640 } else {
2641 irb_.CreateBr(GetUnwindBasicBlock());
2642 }
2643}
2644
2645void GBCExpanderPass::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
Jeff Hao9a142652013-01-17 23:10:19 +00002646 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
2647
TDYa1275e869b62012-07-25 00:45:39 -07002648 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
2649
2650 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
TDYa12755e5e6c2012-09-11 15:14:42 -07002651 landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
TDYa127aa558872012-08-16 05:11:07 -07002652 irb_.GetInsertBlock()));
Jeff Hao9a142652013-01-17 23:10:19 +00002653 irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
TDYa1275e869b62012-07-25 00:45:39 -07002654 } else {
Jeff Hao9a142652013-01-17 23:10:19 +00002655 irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
TDYa1275e869b62012-07-25 00:45:39 -07002656 }
2657
2658 irb_.SetInsertPoint(block_cont);
2659}
2660
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002661llvm::Value*
2662GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
2663 llvm::CallInst& call_inst) {
2664 switch (intr_id) {
2665 //==- Thread -----------------------------------------------------------==//
2666 case IntrinsicHelper::GetCurrentThread: {
TDYa127b672d1e2012-06-28 21:21:45 -07002667 return irb_.Runtime().EmitGetCurrentThread();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002668 }
Logan Chien75e4b602012-07-23 14:24:12 -07002669 case IntrinsicHelper::CheckSuspend: {
TDYa127ce4cc0d2012-11-18 16:59:53 -08002670 Expand_TestSuspend(call_inst);
TDYa127890ea892012-08-22 10:49:42 -07002671 return NULL;
2672 }
2673 case IntrinsicHelper::TestSuspend: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002674 Expand_TestSuspend(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002675 return NULL;
2676 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002677 case IntrinsicHelper::MarkGCCard: {
TDYa1279a129452012-07-19 03:10:08 -07002678 Expand_MarkGCCard(call_inst);
2679 return NULL;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002680 }
Logan Chien75e4b602012-07-23 14:24:12 -07002681
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002682 //==- Exception --------------------------------------------------------==//
2683 case IntrinsicHelper::ThrowException: {
2684 return ExpandToRuntime(runtime_support::ThrowException, call_inst);
2685 }
TDYa127f71bf5a2012-07-29 20:09:52 -07002686 case IntrinsicHelper::HLThrowException: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002687 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2688
2689 EmitUpdateDexPC(dex_pc);
2690
2691 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowException),
2692 call_inst.getArgOperand(0));
2693
2694 EmitGuard_ExceptionLandingPad(dex_pc);
2695 return NULL;
2696 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002697 case IntrinsicHelper::GetException: {
TDYa127823433d2012-09-26 16:03:51 -07002698 return irb_.Runtime().EmitGetAndClearException();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002699 }
2700 case IntrinsicHelper::IsExceptionPending: {
2701 return irb_.Runtime().EmitIsExceptionPending();
2702 }
2703 case IntrinsicHelper::FindCatchBlock: {
2704 return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
2705 }
2706 case IntrinsicHelper::ThrowDivZeroException: {
2707 return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
2708 }
2709 case IntrinsicHelper::ThrowNullPointerException: {
2710 return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
2711 }
2712 case IntrinsicHelper::ThrowIndexOutOfBounds: {
2713 return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
2714 }
Logan Chien75e4b602012-07-23 14:24:12 -07002715
2716 //==- Const String -----------------------------------------------------==//
2717 case IntrinsicHelper::ConstString: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002718 return Expand_ConstString(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002719 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002720 case IntrinsicHelper::LoadStringFromDexCache: {
2721 return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
2722 }
2723 case IntrinsicHelper::ResolveString: {
2724 return ExpandToRuntime(runtime_support::ResolveString, call_inst);
2725 }
Logan Chien75e4b602012-07-23 14:24:12 -07002726
2727 //==- Const Class ------------------------------------------------------==//
2728 case IntrinsicHelper::ConstClass: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002729 return Expand_ConstClass(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002730 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002731 case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
2732 return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
2733 }
2734 case IntrinsicHelper::LoadTypeFromDexCache: {
2735 return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
2736 }
2737 case IntrinsicHelper::InitializeType: {
2738 return ExpandToRuntime(runtime_support::InitializeType, call_inst);
2739 }
Logan Chien75e4b602012-07-23 14:24:12 -07002740
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002741 //==- Lock -------------------------------------------------------------==//
2742 case IntrinsicHelper::LockObject: {
2743 Expand_LockObject(call_inst.getArgOperand(0));
2744 return NULL;
2745 }
2746 case IntrinsicHelper::UnlockObject: {
2747 Expand_UnlockObject(call_inst.getArgOperand(0));
2748 return NULL;
2749 }
Logan Chien75e4b602012-07-23 14:24:12 -07002750
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002751 //==- Cast -------------------------------------------------------------==//
2752 case IntrinsicHelper::CheckCast: {
2753 return ExpandToRuntime(runtime_support::CheckCast, call_inst);
2754 }
Logan Chien75e4b602012-07-23 14:24:12 -07002755 case IntrinsicHelper::HLCheckCast: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002756 Expand_HLCheckCast(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002757 return NULL;
2758 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002759 case IntrinsicHelper::IsAssignable: {
2760 return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
2761 }
Logan Chien75e4b602012-07-23 14:24:12 -07002762
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002763 //==- Alloc ------------------------------------------------------------==//
2764 case IntrinsicHelper::AllocObject: {
2765 return ExpandToRuntime(runtime_support::AllocObject, call_inst);
2766 }
2767 case IntrinsicHelper::AllocObjectWithAccessCheck: {
2768 return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
2769 }
Logan Chien75e4b602012-07-23 14:24:12 -07002770
2771 //==- Instance ---------------------------------------------------------==//
2772 case IntrinsicHelper::NewInstance: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002773 return Expand_NewInstance(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002774 }
2775 case IntrinsicHelper::InstanceOf: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002776 return Expand_InstanceOf(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002777 }
2778
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002779 //==- Array ------------------------------------------------------------==//
Logan Chien75e4b602012-07-23 14:24:12 -07002780 case IntrinsicHelper::NewArray: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002781 return Expand_NewArray(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002782 }
2783 case IntrinsicHelper::OptArrayLength: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002784 return Expand_OptArrayLength(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002785 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002786 case IntrinsicHelper::ArrayLength: {
2787 return EmitLoadArrayLength(call_inst.getArgOperand(0));
2788 }
2789 case IntrinsicHelper::AllocArray: {
2790 return ExpandToRuntime(runtime_support::AllocArray, call_inst);
2791 }
2792 case IntrinsicHelper::AllocArrayWithAccessCheck: {
2793 return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
2794 call_inst);
2795 }
2796 case IntrinsicHelper::CheckAndAllocArray: {
2797 return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
2798 }
2799 case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
2800 return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
2801 call_inst);
2802 }
2803 case IntrinsicHelper::ArrayGet: {
2804 return Expand_ArrayGet(call_inst.getArgOperand(0),
2805 call_inst.getArgOperand(1),
2806 kInt);
2807 }
2808 case IntrinsicHelper::ArrayGetWide: {
2809 return Expand_ArrayGet(call_inst.getArgOperand(0),
2810 call_inst.getArgOperand(1),
2811 kLong);
2812 }
2813 case IntrinsicHelper::ArrayGetObject: {
2814 return Expand_ArrayGet(call_inst.getArgOperand(0),
2815 call_inst.getArgOperand(1),
2816 kObject);
2817 }
2818 case IntrinsicHelper::ArrayGetBoolean: {
2819 return Expand_ArrayGet(call_inst.getArgOperand(0),
2820 call_inst.getArgOperand(1),
2821 kBoolean);
2822 }
2823 case IntrinsicHelper::ArrayGetByte: {
2824 return Expand_ArrayGet(call_inst.getArgOperand(0),
2825 call_inst.getArgOperand(1),
2826 kByte);
2827 }
2828 case IntrinsicHelper::ArrayGetChar: {
2829 return Expand_ArrayGet(call_inst.getArgOperand(0),
2830 call_inst.getArgOperand(1),
2831 kChar);
2832 }
2833 case IntrinsicHelper::ArrayGetShort: {
2834 return Expand_ArrayGet(call_inst.getArgOperand(0),
2835 call_inst.getArgOperand(1),
2836 kShort);
2837 }
2838 case IntrinsicHelper::ArrayPut: {
2839 Expand_ArrayPut(call_inst.getArgOperand(0),
2840 call_inst.getArgOperand(1),
2841 call_inst.getArgOperand(2),
2842 kInt);
2843 return NULL;
2844 }
2845 case IntrinsicHelper::ArrayPutWide: {
2846 Expand_ArrayPut(call_inst.getArgOperand(0),
2847 call_inst.getArgOperand(1),
2848 call_inst.getArgOperand(2),
2849 kLong);
2850 return NULL;
2851 }
2852 case IntrinsicHelper::ArrayPutObject: {
2853 Expand_ArrayPut(call_inst.getArgOperand(0),
2854 call_inst.getArgOperand(1),
2855 call_inst.getArgOperand(2),
2856 kObject);
2857 return NULL;
2858 }
2859 case IntrinsicHelper::ArrayPutBoolean: {
2860 Expand_ArrayPut(call_inst.getArgOperand(0),
2861 call_inst.getArgOperand(1),
2862 call_inst.getArgOperand(2),
2863 kBoolean);
2864 return NULL;
2865 }
2866 case IntrinsicHelper::ArrayPutByte: {
2867 Expand_ArrayPut(call_inst.getArgOperand(0),
2868 call_inst.getArgOperand(1),
2869 call_inst.getArgOperand(2),
2870 kByte);
2871 return NULL;
2872 }
2873 case IntrinsicHelper::ArrayPutChar: {
2874 Expand_ArrayPut(call_inst.getArgOperand(0),
2875 call_inst.getArgOperand(1),
2876 call_inst.getArgOperand(2),
2877 kChar);
2878 return NULL;
2879 }
2880 case IntrinsicHelper::ArrayPutShort: {
2881 Expand_ArrayPut(call_inst.getArgOperand(0),
2882 call_inst.getArgOperand(1),
2883 call_inst.getArgOperand(2),
2884 kShort);
2885 return NULL;
2886 }
2887 case IntrinsicHelper::CheckPutArrayElement: {
2888 return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
2889 }
2890 case IntrinsicHelper::FilledNewArray: {
2891 Expand_FilledNewArray(call_inst);
2892 return NULL;
2893 }
2894 case IntrinsicHelper::FillArrayData: {
2895 return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
2896 }
Logan Chien75e4b602012-07-23 14:24:12 -07002897 case IntrinsicHelper::HLFillArrayData: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002898 Expand_HLFillArrayData(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002899 return NULL;
2900 }
2901 case IntrinsicHelper::HLFilledNewArray: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002902 return Expand_HLFilledNewArray(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002903 }
2904
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002905 //==- Instance Field ---------------------------------------------------==//
2906 case IntrinsicHelper::InstanceFieldGet:
2907 case IntrinsicHelper::InstanceFieldGetBoolean:
2908 case IntrinsicHelper::InstanceFieldGetByte:
2909 case IntrinsicHelper::InstanceFieldGetChar:
2910 case IntrinsicHelper::InstanceFieldGetShort: {
2911 return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
2912 }
2913 case IntrinsicHelper::InstanceFieldGetWide: {
2914 return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
2915 }
2916 case IntrinsicHelper::InstanceFieldGetObject: {
2917 return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
2918 }
2919 case IntrinsicHelper::InstanceFieldGetFast: {
2920 return Expand_IGetFast(call_inst.getArgOperand(0),
2921 call_inst.getArgOperand(1),
2922 call_inst.getArgOperand(2),
2923 kInt);
2924 }
2925 case IntrinsicHelper::InstanceFieldGetWideFast: {
2926 return Expand_IGetFast(call_inst.getArgOperand(0),
2927 call_inst.getArgOperand(1),
2928 call_inst.getArgOperand(2),
2929 kLong);
2930 }
2931 case IntrinsicHelper::InstanceFieldGetObjectFast: {
2932 return Expand_IGetFast(call_inst.getArgOperand(0),
2933 call_inst.getArgOperand(1),
2934 call_inst.getArgOperand(2),
2935 kObject);
2936 }
2937 case IntrinsicHelper::InstanceFieldGetBooleanFast: {
2938 return Expand_IGetFast(call_inst.getArgOperand(0),
2939 call_inst.getArgOperand(1),
2940 call_inst.getArgOperand(2),
2941 kBoolean);
2942 }
2943 case IntrinsicHelper::InstanceFieldGetByteFast: {
2944 return Expand_IGetFast(call_inst.getArgOperand(0),
2945 call_inst.getArgOperand(1),
2946 call_inst.getArgOperand(2),
2947 kByte);
2948 }
2949 case IntrinsicHelper::InstanceFieldGetCharFast: {
2950 return Expand_IGetFast(call_inst.getArgOperand(0),
2951 call_inst.getArgOperand(1),
2952 call_inst.getArgOperand(2),
2953 kChar);
2954 }
2955 case IntrinsicHelper::InstanceFieldGetShortFast: {
2956 return Expand_IGetFast(call_inst.getArgOperand(0),
2957 call_inst.getArgOperand(1),
2958 call_inst.getArgOperand(2),
2959 kShort);
2960 }
2961 case IntrinsicHelper::InstanceFieldPut:
2962 case IntrinsicHelper::InstanceFieldPutBoolean:
2963 case IntrinsicHelper::InstanceFieldPutByte:
2964 case IntrinsicHelper::InstanceFieldPutChar:
2965 case IntrinsicHelper::InstanceFieldPutShort: {
2966 return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
2967 }
2968 case IntrinsicHelper::InstanceFieldPutWide: {
2969 return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
2970 }
2971 case IntrinsicHelper::InstanceFieldPutObject: {
2972 return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
2973 }
2974 case IntrinsicHelper::InstanceFieldPutFast: {
2975 Expand_IPutFast(call_inst.getArgOperand(0),
2976 call_inst.getArgOperand(1),
2977 call_inst.getArgOperand(2),
2978 call_inst.getArgOperand(3),
2979 kInt);
2980 return NULL;
2981 }
2982 case IntrinsicHelper::InstanceFieldPutWideFast: {
2983 Expand_IPutFast(call_inst.getArgOperand(0),
2984 call_inst.getArgOperand(1),
2985 call_inst.getArgOperand(2),
2986 call_inst.getArgOperand(3),
2987 kLong);
2988 return NULL;
2989 }
2990 case IntrinsicHelper::InstanceFieldPutObjectFast: {
2991 Expand_IPutFast(call_inst.getArgOperand(0),
2992 call_inst.getArgOperand(1),
2993 call_inst.getArgOperand(2),
2994 call_inst.getArgOperand(3),
2995 kObject);
2996 return NULL;
2997 }
2998 case IntrinsicHelper::InstanceFieldPutBooleanFast: {
2999 Expand_IPutFast(call_inst.getArgOperand(0),
3000 call_inst.getArgOperand(1),
3001 call_inst.getArgOperand(2),
3002 call_inst.getArgOperand(3),
3003 kBoolean);
3004 return NULL;
3005 }
3006 case IntrinsicHelper::InstanceFieldPutByteFast: {
3007 Expand_IPutFast(call_inst.getArgOperand(0),
3008 call_inst.getArgOperand(1),
3009 call_inst.getArgOperand(2),
3010 call_inst.getArgOperand(3),
3011 kByte);
3012 return NULL;
3013 }
3014 case IntrinsicHelper::InstanceFieldPutCharFast: {
3015 Expand_IPutFast(call_inst.getArgOperand(0),
3016 call_inst.getArgOperand(1),
3017 call_inst.getArgOperand(2),
3018 call_inst.getArgOperand(3),
3019 kChar);
3020 return NULL;
3021 }
3022 case IntrinsicHelper::InstanceFieldPutShortFast: {
3023 Expand_IPutFast(call_inst.getArgOperand(0),
3024 call_inst.getArgOperand(1),
3025 call_inst.getArgOperand(2),
3026 call_inst.getArgOperand(3),
3027 kShort);
3028 return NULL;
3029 }
Logan Chien75e4b602012-07-23 14:24:12 -07003030
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003031 //==- Static Field -----------------------------------------------------==//
3032 case IntrinsicHelper::StaticFieldGet:
3033 case IntrinsicHelper::StaticFieldGetBoolean:
3034 case IntrinsicHelper::StaticFieldGetByte:
3035 case IntrinsicHelper::StaticFieldGetChar:
3036 case IntrinsicHelper::StaticFieldGetShort: {
3037 return ExpandToRuntime(runtime_support::Get32Static, call_inst);
3038 }
3039 case IntrinsicHelper::StaticFieldGetWide: {
3040 return ExpandToRuntime(runtime_support::Get64Static, call_inst);
3041 }
3042 case IntrinsicHelper::StaticFieldGetObject: {
3043 return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
3044 }
3045 case IntrinsicHelper::StaticFieldGetFast: {
3046 return Expand_SGetFast(call_inst.getArgOperand(0),
3047 call_inst.getArgOperand(1),
3048 call_inst.getArgOperand(2),
3049 kInt);
3050 }
3051 case IntrinsicHelper::StaticFieldGetWideFast: {
3052 return Expand_SGetFast(call_inst.getArgOperand(0),
3053 call_inst.getArgOperand(1),
3054 call_inst.getArgOperand(2),
3055 kLong);
3056 }
3057 case IntrinsicHelper::StaticFieldGetObjectFast: {
3058 return Expand_SGetFast(call_inst.getArgOperand(0),
3059 call_inst.getArgOperand(1),
3060 call_inst.getArgOperand(2),
3061 kObject);
3062 }
3063 case IntrinsicHelper::StaticFieldGetBooleanFast: {
3064 return Expand_SGetFast(call_inst.getArgOperand(0),
3065 call_inst.getArgOperand(1),
3066 call_inst.getArgOperand(2),
3067 kBoolean);
3068 }
3069 case IntrinsicHelper::StaticFieldGetByteFast: {
3070 return Expand_SGetFast(call_inst.getArgOperand(0),
3071 call_inst.getArgOperand(1),
3072 call_inst.getArgOperand(2),
3073 kByte);
3074 }
3075 case IntrinsicHelper::StaticFieldGetCharFast: {
3076 return Expand_SGetFast(call_inst.getArgOperand(0),
3077 call_inst.getArgOperand(1),
3078 call_inst.getArgOperand(2),
3079 kChar);
3080 }
3081 case IntrinsicHelper::StaticFieldGetShortFast: {
3082 return Expand_SGetFast(call_inst.getArgOperand(0),
3083 call_inst.getArgOperand(1),
3084 call_inst.getArgOperand(2),
3085 kShort);
3086 }
3087 case IntrinsicHelper::StaticFieldPut:
3088 case IntrinsicHelper::StaticFieldPutBoolean:
3089 case IntrinsicHelper::StaticFieldPutByte:
3090 case IntrinsicHelper::StaticFieldPutChar:
3091 case IntrinsicHelper::StaticFieldPutShort: {
3092 return ExpandToRuntime(runtime_support::Set32Static, call_inst);
3093 }
3094 case IntrinsicHelper::StaticFieldPutWide: {
3095 return ExpandToRuntime(runtime_support::Set64Static, call_inst);
3096 }
3097 case IntrinsicHelper::StaticFieldPutObject: {
3098 return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
3099 }
3100 case IntrinsicHelper::StaticFieldPutFast: {
3101 Expand_SPutFast(call_inst.getArgOperand(0),
3102 call_inst.getArgOperand(1),
3103 call_inst.getArgOperand(2),
3104 call_inst.getArgOperand(3),
3105 kInt);
3106 return NULL;
3107 }
3108 case IntrinsicHelper::StaticFieldPutWideFast: {
3109 Expand_SPutFast(call_inst.getArgOperand(0),
3110 call_inst.getArgOperand(1),
3111 call_inst.getArgOperand(2),
3112 call_inst.getArgOperand(3),
3113 kLong);
3114 return NULL;
3115 }
3116 case IntrinsicHelper::StaticFieldPutObjectFast: {
3117 Expand_SPutFast(call_inst.getArgOperand(0),
3118 call_inst.getArgOperand(1),
3119 call_inst.getArgOperand(2),
3120 call_inst.getArgOperand(3),
3121 kObject);
3122 return NULL;
3123 }
3124 case IntrinsicHelper::StaticFieldPutBooleanFast: {
3125 Expand_SPutFast(call_inst.getArgOperand(0),
3126 call_inst.getArgOperand(1),
3127 call_inst.getArgOperand(2),
3128 call_inst.getArgOperand(3),
3129 kBoolean);
3130 return NULL;
3131 }
3132 case IntrinsicHelper::StaticFieldPutByteFast: {
3133 Expand_SPutFast(call_inst.getArgOperand(0),
3134 call_inst.getArgOperand(1),
3135 call_inst.getArgOperand(2),
3136 call_inst.getArgOperand(3),
3137 kByte);
3138 return NULL;
3139 }
3140 case IntrinsicHelper::StaticFieldPutCharFast: {
3141 Expand_SPutFast(call_inst.getArgOperand(0),
3142 call_inst.getArgOperand(1),
3143 call_inst.getArgOperand(2),
3144 call_inst.getArgOperand(3),
3145 kChar);
3146 return NULL;
3147 }
3148 case IntrinsicHelper::StaticFieldPutShortFast: {
3149 Expand_SPutFast(call_inst.getArgOperand(0),
3150 call_inst.getArgOperand(1),
3151 call_inst.getArgOperand(2),
3152 call_inst.getArgOperand(3),
3153 kShort);
3154 return NULL;
3155 }
3156 case IntrinsicHelper::LoadDeclaringClassSSB: {
3157 return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
3158 }
3159 case IntrinsicHelper::LoadClassSSBFromDexCache: {
3160 return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
3161 }
3162 case IntrinsicHelper::InitializeAndLoadClassSSB: {
3163 return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
3164 }
Logan Chien75e4b602012-07-23 14:24:12 -07003165
3166 //==- High-level Array -------------------------------------------------==//
3167 case IntrinsicHelper::HLArrayGet: {
TDYa1275a26d442012-07-26 18:58:38 -07003168 return Expand_HLArrayGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003169 }
3170 case IntrinsicHelper::HLArrayGetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003171 return Expand_HLArrayGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003172 }
3173 case IntrinsicHelper::HLArrayGetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003174 return Expand_HLArrayGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003175 }
3176 case IntrinsicHelper::HLArrayGetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003177 return Expand_HLArrayGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003178 }
3179 case IntrinsicHelper::HLArrayGetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003180 return Expand_HLArrayGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003181 }
3182 case IntrinsicHelper::HLArrayGetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003183 return Expand_HLArrayGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003184 }
3185 case IntrinsicHelper::HLArrayGetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003186 return Expand_HLArrayGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003187 }
3188 case IntrinsicHelper::HLArrayGetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003189 return Expand_HLArrayGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003190 }
3191 case IntrinsicHelper::HLArrayGetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003192 return Expand_HLArrayGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003193 }
3194 case IntrinsicHelper::HLArrayPut: {
TDYa1275a26d442012-07-26 18:58:38 -07003195 Expand_HLArrayPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003196 return NULL;
3197 }
3198 case IntrinsicHelper::HLArrayPutBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003199 Expand_HLArrayPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003200 return NULL;
3201 }
3202 case IntrinsicHelper::HLArrayPutByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003203 Expand_HLArrayPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003204 return NULL;
3205 }
3206 case IntrinsicHelper::HLArrayPutChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003207 Expand_HLArrayPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003208 return NULL;
3209 }
3210 case IntrinsicHelper::HLArrayPutShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003211 Expand_HLArrayPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003212 return NULL;
3213 }
3214 case IntrinsicHelper::HLArrayPutFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003215 Expand_HLArrayPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003216 return NULL;
3217 }
3218 case IntrinsicHelper::HLArrayPutWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003219 Expand_HLArrayPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003220 return NULL;
3221 }
3222 case IntrinsicHelper::HLArrayPutDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003223 Expand_HLArrayPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003224 return NULL;
3225 }
3226 case IntrinsicHelper::HLArrayPutObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003227 Expand_HLArrayPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003228 return NULL;
3229 }
3230
3231 //==- High-level Instance ----------------------------------------------==//
3232 case IntrinsicHelper::HLIGet: {
TDYa1275e869b62012-07-25 00:45:39 -07003233 return Expand_HLIGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003234 }
3235 case IntrinsicHelper::HLIGetBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07003236 return Expand_HLIGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003237 }
3238 case IntrinsicHelper::HLIGetByte: {
TDYa1275e869b62012-07-25 00:45:39 -07003239 return Expand_HLIGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003240 }
3241 case IntrinsicHelper::HLIGetChar: {
TDYa1275e869b62012-07-25 00:45:39 -07003242 return Expand_HLIGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003243 }
3244 case IntrinsicHelper::HLIGetShort: {
TDYa1275e869b62012-07-25 00:45:39 -07003245 return Expand_HLIGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003246 }
3247 case IntrinsicHelper::HLIGetFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07003248 return Expand_HLIGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003249 }
3250 case IntrinsicHelper::HLIGetWide: {
TDYa1275e869b62012-07-25 00:45:39 -07003251 return Expand_HLIGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003252 }
3253 case IntrinsicHelper::HLIGetDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07003254 return Expand_HLIGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003255 }
3256 case IntrinsicHelper::HLIGetObject: {
TDYa1275e869b62012-07-25 00:45:39 -07003257 return Expand_HLIGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003258 }
3259 case IntrinsicHelper::HLIPut: {
TDYa1275e869b62012-07-25 00:45:39 -07003260 Expand_HLIPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003261 return NULL;
3262 }
3263 case IntrinsicHelper::HLIPutBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07003264 Expand_HLIPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003265 return NULL;
3266 }
3267 case IntrinsicHelper::HLIPutByte: {
TDYa1275e869b62012-07-25 00:45:39 -07003268 Expand_HLIPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003269 return NULL;
3270 }
3271 case IntrinsicHelper::HLIPutChar: {
TDYa1275e869b62012-07-25 00:45:39 -07003272 Expand_HLIPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003273 return NULL;
3274 }
3275 case IntrinsicHelper::HLIPutShort: {
TDYa1275e869b62012-07-25 00:45:39 -07003276 Expand_HLIPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003277 return NULL;
3278 }
3279 case IntrinsicHelper::HLIPutFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07003280 Expand_HLIPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003281 return NULL;
3282 }
3283 case IntrinsicHelper::HLIPutWide: {
TDYa1275e869b62012-07-25 00:45:39 -07003284 Expand_HLIPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003285 return NULL;
3286 }
3287 case IntrinsicHelper::HLIPutDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07003288 Expand_HLIPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003289 return NULL;
3290 }
3291 case IntrinsicHelper::HLIPutObject: {
TDYa1275e869b62012-07-25 00:45:39 -07003292 Expand_HLIPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003293 return NULL;
3294 }
3295
3296 //==- High-level Invoke ------------------------------------------------==//
TDYa127f71bf5a2012-07-29 20:09:52 -07003297 case IntrinsicHelper::HLInvokeVoid:
3298 case IntrinsicHelper::HLInvokeObj:
3299 case IntrinsicHelper::HLInvokeInt:
3300 case IntrinsicHelper::HLInvokeFloat:
3301 case IntrinsicHelper::HLInvokeLong:
Logan Chien75e4b602012-07-23 14:24:12 -07003302 case IntrinsicHelper::HLInvokeDouble: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003303 return Expand_HLInvoke(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003304 }
3305
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003306 //==- Invoke -----------------------------------------------------------==//
3307 case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
3308 return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
3309 }
3310 case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
3311 return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
3312 }
3313 case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
3314 return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
3315 }
3316 case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
3317 return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
3318 }
3319 case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
3320 return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
3321 }
3322 case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
3323 return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
3324 }
3325 case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
3326 return Expand_GetVirtualCalleeMethodObjAddrFast(
3327 call_inst.getArgOperand(0), call_inst.getArgOperand(1));
3328 }
3329 case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
3330 return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
3331 }
3332 case IntrinsicHelper::InvokeRetVoid:
3333 case IntrinsicHelper::InvokeRetBoolean:
3334 case IntrinsicHelper::InvokeRetByte:
3335 case IntrinsicHelper::InvokeRetChar:
3336 case IntrinsicHelper::InvokeRetShort:
3337 case IntrinsicHelper::InvokeRetInt:
3338 case IntrinsicHelper::InvokeRetLong:
3339 case IntrinsicHelper::InvokeRetFloat:
3340 case IntrinsicHelper::InvokeRetDouble:
3341 case IntrinsicHelper::InvokeRetObject: {
3342 return Expand_Invoke(call_inst);
3343 }
Logan Chien75e4b602012-07-23 14:24:12 -07003344
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003345 //==- Math -------------------------------------------------------------==//
3346 case IntrinsicHelper::DivInt: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003347 return Expand_DivRem(call_inst, /* is_div */true, kInt);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003348 }
3349 case IntrinsicHelper::RemInt: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003350 return Expand_DivRem(call_inst, /* is_div */false, kInt);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003351 }
3352 case IntrinsicHelper::DivLong: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003353 return Expand_DivRem(call_inst, /* is_div */true, kLong);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003354 }
3355 case IntrinsicHelper::RemLong: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003356 return Expand_DivRem(call_inst, /* is_div */false, kLong);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003357 }
3358 case IntrinsicHelper::D2L: {
3359 return ExpandToRuntime(runtime_support::art_d2l, call_inst);
3360 }
3361 case IntrinsicHelper::D2I: {
3362 return ExpandToRuntime(runtime_support::art_d2i, call_inst);
3363 }
3364 case IntrinsicHelper::F2L: {
3365 return ExpandToRuntime(runtime_support::art_f2l, call_inst);
3366 }
3367 case IntrinsicHelper::F2I: {
3368 return ExpandToRuntime(runtime_support::art_f2i, call_inst);
3369 }
Logan Chien75e4b602012-07-23 14:24:12 -07003370
3371 //==- High-level Static ------------------------------------------------==//
3372 case IntrinsicHelper::HLSget: {
TDYa1275a26d442012-07-26 18:58:38 -07003373 return Expand_HLSget(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003374 }
3375 case IntrinsicHelper::HLSgetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003376 return Expand_HLSget(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003377 }
3378 case IntrinsicHelper::HLSgetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003379 return Expand_HLSget(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003380 }
3381 case IntrinsicHelper::HLSgetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003382 return Expand_HLSget(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003383 }
3384 case IntrinsicHelper::HLSgetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003385 return Expand_HLSget(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003386 }
3387 case IntrinsicHelper::HLSgetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003388 return Expand_HLSget(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003389 }
3390 case IntrinsicHelper::HLSgetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003391 return Expand_HLSget(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003392 }
3393 case IntrinsicHelper::HLSgetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003394 return Expand_HLSget(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003395 }
3396 case IntrinsicHelper::HLSgetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003397 return Expand_HLSget(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003398 }
3399 case IntrinsicHelper::HLSput: {
TDYa1275a26d442012-07-26 18:58:38 -07003400 Expand_HLSput(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003401 return NULL;
3402 }
3403 case IntrinsicHelper::HLSputBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003404 Expand_HLSput(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003405 return NULL;
3406 }
3407 case IntrinsicHelper::HLSputByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003408 Expand_HLSput(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003409 return NULL;
3410 }
3411 case IntrinsicHelper::HLSputChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003412 Expand_HLSput(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003413 return NULL;
3414 }
3415 case IntrinsicHelper::HLSputShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003416 Expand_HLSput(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003417 return NULL;
3418 }
3419 case IntrinsicHelper::HLSputFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003420 Expand_HLSput(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003421 return NULL;
3422 }
3423 case IntrinsicHelper::HLSputWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003424 Expand_HLSput(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003425 return NULL;
3426 }
3427 case IntrinsicHelper::HLSputDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003428 Expand_HLSput(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003429 return NULL;
3430 }
3431 case IntrinsicHelper::HLSputObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003432 Expand_HLSput(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003433 return NULL;
3434 }
3435
3436 //==- High-level Monitor -----------------------------------------------==//
3437 case IntrinsicHelper::MonitorEnter: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003438 Expand_MonitorEnter(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003439 return NULL;
3440 }
3441 case IntrinsicHelper::MonitorExit: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003442 Expand_MonitorExit(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003443 return NULL;
3444 }
3445
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003446 //==- Shadow Frame -----------------------------------------------------==//
3447 case IntrinsicHelper::AllocaShadowFrame: {
TDYa127ce4cc0d2012-11-18 16:59:53 -08003448 Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003449 return NULL;
3450 }
TDYa1278e950c12012-11-02 09:58:19 -07003451 case IntrinsicHelper::SetVReg: {
3452 Expand_SetVReg(call_inst.getArgOperand(0),
3453 call_inst.getArgOperand(1));
3454 return NULL;
3455 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003456 case IntrinsicHelper::PopShadowFrame: {
3457 Expand_PopShadowFrame();
3458 return NULL;
3459 }
3460 case IntrinsicHelper::UpdateDexPC: {
3461 Expand_UpdateDexPC(call_inst.getArgOperand(0));
3462 return NULL;
3463 }
TDYa127a1b21852012-07-23 03:20:39 -07003464
Logan Chien75e4b602012-07-23 14:24:12 -07003465 //==- Comparison -------------------------------------------------------==//
3466 case IntrinsicHelper::CmplFloat:
3467 case IntrinsicHelper::CmplDouble: {
3468 return Expand_FPCompare(call_inst.getArgOperand(0),
3469 call_inst.getArgOperand(1),
3470 false);
3471 }
3472 case IntrinsicHelper::CmpgFloat:
3473 case IntrinsicHelper::CmpgDouble: {
3474 return Expand_FPCompare(call_inst.getArgOperand(0),
3475 call_inst.getArgOperand(1),
3476 true);
3477 }
3478 case IntrinsicHelper::CmpLong: {
3479 return Expand_LongCompare(call_inst.getArgOperand(0),
3480 call_inst.getArgOperand(1));
3481 }
TDYa127a1b21852012-07-23 03:20:39 -07003482
Logan Chien75e4b602012-07-23 14:24:12 -07003483 //==- Const ------------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003484 case IntrinsicHelper::ConstInt:
3485 case IntrinsicHelper::ConstLong: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003486 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07003487 }
TDYa127920be7c2012-09-10 17:13:22 -07003488 case IntrinsicHelper::ConstFloat: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003489 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3490 irb_.getJFloatTy());
Logan Chien75e4b602012-07-23 14:24:12 -07003491 }
TDYa127920be7c2012-09-10 17:13:22 -07003492 case IntrinsicHelper::ConstDouble: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003493 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3494 irb_.getJDoubleTy());
3495 }
TDYa127920be7c2012-09-10 17:13:22 -07003496 case IntrinsicHelper::ConstObj: {
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07003497 CHECK(LV2UInt(call_inst.getArgOperand(0)) == 0);
3498 return irb_.getJNull();
Logan Chien75e4b602012-07-23 14:24:12 -07003499 }
3500
3501 //==- Method Info ------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003502 case IntrinsicHelper::MethodInfo: {
Shih-wei Liaob2596522012-09-14 16:36:11 -07003503 // Nothing to be done, because MethodInfo carries optional hints that are
3504 // not needed by the portable path.
Logan Chien75e4b602012-07-23 14:24:12 -07003505 return NULL;
3506 }
3507
3508 //==- Copy -------------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003509 case IntrinsicHelper::CopyInt:
3510 case IntrinsicHelper::CopyFloat:
3511 case IntrinsicHelper::CopyLong:
3512 case IntrinsicHelper::CopyDouble:
3513 case IntrinsicHelper::CopyObj: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003514 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07003515 }
3516
3517 //==- Shift ------------------------------------------------------------==//
TDYa127920be7c2012-09-10 17:13:22 -07003518 case IntrinsicHelper::SHLLong: {
Logan Chien75e4b602012-07-23 14:24:12 -07003519 return Expand_IntegerShift(call_inst.getArgOperand(0),
3520 call_inst.getArgOperand(1),
3521 kIntegerSHL, kLong);
3522 }
TDYa127920be7c2012-09-10 17:13:22 -07003523 case IntrinsicHelper::SHRLong: {
Logan Chien75e4b602012-07-23 14:24:12 -07003524 return Expand_IntegerShift(call_inst.getArgOperand(0),
3525 call_inst.getArgOperand(1),
3526 kIntegerSHR, kLong);
3527 }
TDYa127920be7c2012-09-10 17:13:22 -07003528 case IntrinsicHelper::USHRLong: {
Logan Chien75e4b602012-07-23 14:24:12 -07003529 return Expand_IntegerShift(call_inst.getArgOperand(0),
3530 call_inst.getArgOperand(1),
3531 kIntegerUSHR, kLong);
3532 }
TDYa127920be7c2012-09-10 17:13:22 -07003533 case IntrinsicHelper::SHLInt: {
Logan Chien75e4b602012-07-23 14:24:12 -07003534 return Expand_IntegerShift(call_inst.getArgOperand(0),
3535 call_inst.getArgOperand(1),
3536 kIntegerSHL, kInt);
3537 }
TDYa127920be7c2012-09-10 17:13:22 -07003538 case IntrinsicHelper::SHRInt: {
Logan Chien75e4b602012-07-23 14:24:12 -07003539 return Expand_IntegerShift(call_inst.getArgOperand(0),
3540 call_inst.getArgOperand(1),
3541 kIntegerSHR, kInt);
3542 }
TDYa127920be7c2012-09-10 17:13:22 -07003543 case IntrinsicHelper::USHRInt: {
Logan Chien75e4b602012-07-23 14:24:12 -07003544 return Expand_IntegerShift(call_inst.getArgOperand(0),
3545 call_inst.getArgOperand(1),
3546 kIntegerUSHR, kInt);
3547 }
3548
3549 //==- Conversion -------------------------------------------------------==//
TDYa127a1b21852012-07-23 03:20:39 -07003550 case IntrinsicHelper::IntToChar: {
3551 return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
3552 irb_.getJIntTy());
3553 }
3554 case IntrinsicHelper::IntToShort: {
3555 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
3556 irb_.getJIntTy());
3557 }
3558 case IntrinsicHelper::IntToByte: {
3559 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
3560 irb_.getJIntTy());
3561 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003562
TDYa12787caa7e2012-08-25 23:23:27 -07003563 //==- Exception --------------------------------------------------------==//
3564 case IntrinsicHelper::CatchTargets: {
TDYa12755e5e6c2012-09-11 15:14:42 -07003565 UpdatePhiInstruction(current_bb_, irb_.GetInsertBlock());
TDYa12787caa7e2012-08-25 23:23:27 -07003566 llvm::SwitchInst* si = llvm::dyn_cast<llvm::SwitchInst>(call_inst.getNextNode());
3567 CHECK(si != NULL);
3568 irb_.CreateBr(si->getDefaultDest());
3569 si->eraseFromParent();
3570 return call_inst.getArgOperand(0);
3571 }
3572
Logan Chien75e4b602012-07-23 14:24:12 -07003573 //==- Unknown Cases ----------------------------------------------------==//
3574 case IntrinsicHelper::MaxIntrinsicId:
3575 case IntrinsicHelper::UnknownId:
3576 //default:
3577 // NOTE: "default" is intentionally commented so that C/C++ compiler will
3578 // give some warning on unmatched cases.
3579 // NOTE: We should not implement these cases.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003580 break;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003581 }
Logan Chien75e4b602012-07-23 14:24:12 -07003582 UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003583 return NULL;
3584}
3585
3586} // anonymous namespace
3587
3588namespace art {
Shih-wei Liaob2596522012-09-14 16:36:11 -07003589
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003590namespace compiler_llvm {
3591
3592llvm::FunctionPass*
3593CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb) {
3594 return new GBCExpanderPass(intrinsic_helper, irb);
3595}
3596
Shih-wei Liaobb33f2f2012-08-23 13:20:00 -07003597llvm::FunctionPass*
3598CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
3599 Compiler* compiler, OatCompilationUnit* oat_compilation_unit) {
3600 if (compiler != NULL) {
3601 return new GBCExpanderPass(intrinsic_helper, irb,
3602 compiler, oat_compilation_unit);
3603 } else {
3604 return new GBCExpanderPass(intrinsic_helper, irb);
3605 }
3606}
3607
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003608} // namespace compiler_llvm
3609} // namespace art