blob: fbd4a11c032df921eb714dbfc897fd42980094f6 [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"
TDYa1275e869b62012-07-25 00:45:39 -070022#include "oat_compilation_unit.h"
Shih-wei Liao21d28f52012-06-12 05:55:00 -070023#include "object.h"
24#include "thread.h"
TDYa1275e869b62012-07-25 00:45:39 -070025#include "verifier/method_verifier.h"
Shih-wei Liao21d28f52012-06-12 05:55:00 -070026
27#include <llvm/ADT/STLExtras.h>
28#include <llvm/Intrinsics.h>
Logan Chiend36a2ac2012-08-04 00:37:30 +080029#include <llvm/Metadata.h>
Shih-wei Liao21d28f52012-06-12 05:55:00 -070030#include <llvm/Pass.h>
31#include <llvm/Support/CFG.h>
32#include <llvm/Support/InstIterator.h>
33
34#include <vector>
35
36using namespace art;
37using namespace compiler_llvm;
38
39using art::greenland::IntrinsicHelper;
40
41namespace {
42
43class GBCExpanderPass : public llvm::FunctionPass {
44 private:
45 const IntrinsicHelper& intrinsic_helper_;
46 IRBuilder& irb_;
47
48 llvm::LLVMContext& context_;
49 RuntimeSupportBuilder& rtb_;
50
51 private:
52 llvm::AllocaInst* shadow_frame_;
53 llvm::Value* old_shadow_frame_;
54 uint32_t shadow_frame_size_;
55
56 private:
TDYa1275e869b62012-07-25 00:45:39 -070057 Compiler* compiler_;
58
59 const DexFile* dex_file_;
60 DexCache* dex_cache_;
61 const DexFile::CodeItem* code_item_;
62
63 OatCompilationUnit* oat_compilation_unit_;
64
65 uint32_t method_idx_;
66
67 llvm::Function* func_;
68
69 std::vector<llvm::BasicBlock*> basic_blocks_;
70
71 std::vector<llvm::BasicBlock*> basic_block_landing_pads_;
72 llvm::BasicBlock* basic_block_unwind_;
73
Logan Chien67645d82012-08-17 09:10:54 +080074 bool changed_;
75
TDYa1275e869b62012-07-25 00:45:39 -070076 private:
Shih-wei Liao21d28f52012-06-12 05:55:00 -070077 //----------------------------------------------------------------------------
Logan Chien75e4b602012-07-23 14:24:12 -070078 // Constant for GBC expansion
79 //----------------------------------------------------------------------------
80 enum IntegerShiftKind {
81 kIntegerSHL,
82 kIntegerSHR,
83 kIntegerUSHR,
84 };
85
86 private:
87 //----------------------------------------------------------------------------
Shih-wei Liao21d28f52012-06-12 05:55:00 -070088 // Helper function for GBC expansion
89 //----------------------------------------------------------------------------
90
Shih-wei Liao21d28f52012-06-12 05:55:00 -070091 llvm::Value* ExpandToRuntime(runtime_support::RuntimeId rt,
92 llvm::CallInst& inst);
93
TDYa1275e869b62012-07-25 00:45:39 -070094 uint64_t LV2UInt(llvm::Value* lv) {
95 return llvm::cast<llvm::ConstantInt>(lv)->getZExtValue();
96 }
97
98 int64_t LV2SInt(llvm::Value* lv) {
99 return llvm::cast<llvm::ConstantInt>(lv)->getSExtValue();
100 }
101
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700102 private:
103 // TODO: Almost all Emit* are directly copy-n-paste from MethodCompiler.
104 // Refactor these utility functions from MethodCompiler to avoid forking.
105
Logan Chien67645d82012-08-17 09:10:54 +0800106 void EmitStackOverflowCheck(llvm::Instruction* first_non_alloca);
107
108 void RewriteFunction();
109
110 void RewriteBasicBlock(llvm::BasicBlock* original_block);
111
112 void UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
113 llvm::BasicBlock* new_basic_block);
114
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700115
116 //----------------------------------------------------------------------------
117 // Dex cache code generation helper function
118 //----------------------------------------------------------------------------
119 llvm::Value* EmitLoadDexCacheAddr(MemberOffset dex_cache_offset);
120
121 llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
122
123 llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
124
125 llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
126
127 llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
128
129 //----------------------------------------------------------------------------
130 // Code generation helper function
131 //----------------------------------------------------------------------------
132 llvm::Value* EmitLoadMethodObjectAddr();
133
134 llvm::Value* EmitLoadArrayLength(llvm::Value* array);
135
136 llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
137
138 llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
139 llvm::Value* this_addr);
140
141 llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
142 llvm::Value* index_value,
143 JType elem_jty);
144
145 private:
146 //----------------------------------------------------------------------------
147 // Expand Greenland intrinsics
148 //----------------------------------------------------------------------------
149 void Expand_TestSuspend(llvm::CallInst& call_inst);
150
TDYa1279a129452012-07-19 03:10:08 -0700151 void Expand_MarkGCCard(llvm::CallInst& call_inst);
152
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700153 llvm::Value* Expand_GetException();
154
155 llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
156
157 llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
158
159 void Expand_LockObject(llvm::Value* obj);
160
161 void Expand_UnlockObject(llvm::Value* obj);
162
163 llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
164 llvm::Value* index_value,
165 JType elem_jty);
166
167 void Expand_ArrayPut(llvm::Value* new_value,
168 llvm::Value* array_addr,
169 llvm::Value* index_value,
170 JType elem_jty);
171
172 void Expand_FilledNewArray(llvm::CallInst& call_inst);
173
174 llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
175 llvm::Value* is_volatile_value,
176 llvm::Value* object_addr,
177 JType field_jty);
178
179 void Expand_IPutFast(llvm::Value* field_offset_value,
180 llvm::Value* is_volatile_value,
181 llvm::Value* object_addr,
182 llvm::Value* new_value,
183 JType field_jty);
184
185 llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
186 llvm::Value* field_offset_value,
187 llvm::Value* is_volatile_value,
188 JType field_jty);
189
190 void Expand_SPutFast(llvm::Value* static_storage_addr,
191 llvm::Value* field_offset_value,
192 llvm::Value* is_volatile_value,
193 llvm::Value* new_value,
194 JType field_jty);
195
196 llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
197
198 llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
199
200 llvm::Value*
201 Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
202
203 llvm::Value*
204 Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
205 llvm::Value* this_addr);
206
207 llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
208
TDYa1274ec8ccd2012-08-11 07:04:57 -0700209 llvm::Value* Expand_DivRem(llvm::CallInst& call_inst, bool is_div, JType op_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700210
211 void Expand_AllocaShadowFrame(llvm::Value* num_entry_value);
212
213 void Expand_SetShadowFrameEntry(llvm::Value* obj, llvm::Value* entry_idx);
214
215 void Expand_PopShadowFrame();
216
217 void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
218
TDYa127a1b21852012-07-23 03:20:39 -0700219 //----------------------------------------------------------------------------
220 // Quick
221 //----------------------------------------------------------------------------
222
223 llvm::Value* Expand_FPCompare(llvm::Value* src1_value,
224 llvm::Value* src2_value,
225 bool gt_bias);
226
227 llvm::Value* Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value);
228
229 llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
230 llvm::Value* cmp_lt);
231
TDYa127f71bf5a2012-07-29 20:09:52 -0700232 llvm::Value* EmitLoadConstantClass(uint32_t dex_pc, uint32_t type_idx);
TDYa1275a26d442012-07-26 18:58:38 -0700233 llvm::Value* EmitLoadStaticStorage(uint32_t dex_pc, uint32_t type_idx);
234
TDYa1275e869b62012-07-25 00:45:39 -0700235 llvm::Value* Expand_HLIGet(llvm::CallInst& call_inst, JType field_jty);
236 void Expand_HLIPut(llvm::CallInst& call_inst, JType field_jty);
237
TDYa1275a26d442012-07-26 18:58:38 -0700238 llvm::Value* Expand_HLSget(llvm::CallInst& call_inst, JType field_jty);
239 void Expand_HLSput(llvm::CallInst& call_inst, JType field_jty);
240
241 llvm::Value* Expand_HLArrayGet(llvm::CallInst& call_inst, JType field_jty);
242 void Expand_HLArrayPut(llvm::CallInst& call_inst, JType field_jty);
243
TDYa127f71bf5a2012-07-29 20:09:52 -0700244 llvm::Value* Expand_ConstString(llvm::CallInst& call_inst);
245 llvm::Value* Expand_ConstClass(llvm::CallInst& call_inst);
246
247 void Expand_MonitorEnter(llvm::CallInst& call_inst);
248 void Expand_MonitorExit(llvm::CallInst& call_inst);
249
250 void Expand_HLCheckCast(llvm::CallInst& call_inst);
251 llvm::Value* Expand_InstanceOf(llvm::CallInst& call_inst);
252
253 llvm::Value* Expand_NewInstance(llvm::CallInst& call_inst);
254
255 llvm::Value* Expand_HLInvoke(llvm::CallInst& call_inst);
256
257 llvm::Value* Expand_OptArrayLength(llvm::CallInst& call_inst);
258 llvm::Value* Expand_NewArray(llvm::CallInst& call_inst);
259 llvm::Value* Expand_HLFilledNewArray(llvm::CallInst& call_inst);
260 void Expand_HLFillArrayData(llvm::CallInst& call_inst);
261
262 llvm::Value* EmitAllocNewArray(uint32_t dex_pc,
263 llvm::Value* array_length_value,
264 uint32_t type_idx,
265 bool is_filled_new_array);
266
267 llvm::Value* EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
268 InvokeType invoke_type,
269 llvm::Value* this_addr,
270 uint32_t dex_pc,
271 bool is_fast_path);
272
TDYa1275e869b62012-07-25 00:45:39 -0700273 void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
274
275 void EmitUpdateDexPC(uint32_t dex_pc);
276
277 void EmitGuard_DivZeroException(uint32_t dex_pc,
278 llvm::Value* denominator,
279 JType op_jty);
280
281 void EmitGuard_NullPointerException(uint32_t dex_pc,
282 llvm::Value* object);
283
284 void EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
285 llvm::Value* array,
286 llvm::Value* index);
287
288 void EmitGuard_ArrayException(uint32_t dex_pc,
289 llvm::Value* array,
290 llvm::Value* index);
291
292 llvm::FunctionType* GetFunctionType(uint32_t method_idx, bool is_static);
293
294 llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
295
296 llvm::BasicBlock* CreateBasicBlockWithDexPC(uint32_t dex_pc,
297 const char* postfix);
298
299 int32_t GetTryItemOffset(uint32_t dex_pc);
300
301 llvm::BasicBlock* GetLandingPadBasicBlock(uint32_t dex_pc);
302
303 llvm::BasicBlock* GetUnwindBasicBlock();
304
305 void EmitGuard_ExceptionLandingPad(uint32_t dex_pc);
306
307 void EmitBranchExceptionLandingPad(uint32_t dex_pc);
308
Logan Chien75e4b602012-07-23 14:24:12 -0700309 //----------------------------------------------------------------------------
310 // Expand Arithmetic Helper Intrinsics
311 //----------------------------------------------------------------------------
312
313 llvm::Value* Expand_IntegerShift(llvm::Value* src1_value,
314 llvm::Value* src2_value,
315 IntegerShiftKind kind,
316 JType op_jty);
317
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700318 public:
319 static char ID;
320
321 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb)
322 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
Logan Chiene5b8f8b2012-08-13 11:45:05 +0800323 context_(irb.getContext()), rtb_(irb.Runtime()),
324
325 // TODO: Initialize these fields correctly.
326 shadow_frame_(NULL), old_shadow_frame_(NULL), shadow_frame_size_(0),
327 compiler_(NULL), dex_file_(NULL), dex_cache_(NULL), code_item_(NULL),
Logan Chien67645d82012-08-17 09:10:54 +0800328 oat_compilation_unit_(NULL), method_idx_(-1u), func_(NULL),
329 changed_(false)
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700330 { }
331
332 bool runOnFunction(llvm::Function& func);
333
334 private:
Logan Chien67645d82012-08-17 09:10:54 +0800335 void InsertStackOverflowCheck(llvm::Function& func);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700336
337 llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
338 llvm::CallInst& call_inst);
339
340};
341
342char GBCExpanderPass::ID = 0;
343
344bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
TDYa127b672d1e2012-06-28 21:21:45 -0700345 // Runtime support or stub
346 if (func.getName().startswith("art_") || func.getName().startswith("Art")) {
347 return false;
348 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700349
Logan Chien67645d82012-08-17 09:10:54 +0800350 // Setup rewrite context
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700351 shadow_frame_ = NULL;
352 old_shadow_frame_ = NULL;
353 shadow_frame_size_ = 0;
TDYa1275e869b62012-07-25 00:45:39 -0700354 func_ = &func;
Logan Chien67645d82012-08-17 09:10:54 +0800355 changed_ = false; // Assume unchanged
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700356
Logan Chien67645d82012-08-17 09:10:54 +0800357 // Insert stack overflow check
358 InsertStackOverflowCheck(func); // TODO: Use intrinsic.
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700359
Logan Chien67645d82012-08-17 09:10:54 +0800360 // Rewrite the intrinsics
361 RewriteFunction();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700362
363 VERIFY_LLVM_FUNCTION(func);
364
Logan Chien67645d82012-08-17 09:10:54 +0800365 return changed_;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700366}
367
Logan Chien67645d82012-08-17 09:10:54 +0800368void GBCExpanderPass::RewriteBasicBlock(llvm::BasicBlock* original_block) {
369 llvm::BasicBlock* curr_basic_block = original_block;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700370
Logan Chien67645d82012-08-17 09:10:54 +0800371 llvm::BasicBlock::iterator inst_iter = original_block->begin();
372 llvm::BasicBlock::iterator inst_end = original_block->end();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700373
Logan Chien67645d82012-08-17 09:10:54 +0800374 while (inst_iter != inst_end) {
375 llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst_iter);
376 IntrinsicHelper::IntrinsicId intr_id = IntrinsicHelper::UnknownId;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700377
Logan Chien67645d82012-08-17 09:10:54 +0800378 if (call_inst) {
379 llvm::Function* callee_func = call_inst->getCalledFunction();
380 intr_id = intrinsic_helper_.GetIntrinsicId(callee_func);
381 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700382
Logan Chien67645d82012-08-17 09:10:54 +0800383 if (intr_id == IntrinsicHelper::UnknownId) {
384 // This is not intrinsic call. Skip this instruction.
385 ++inst_iter;
386 continue;
387 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700388
Logan Chien67645d82012-08-17 09:10:54 +0800389 // Rewrite the intrinsic and change the function
390 changed_ = true;
391 irb_.SetInsertPoint(inst_iter);
392
393 // Expand the intrinsic
394 if (llvm::Value* new_value = ExpandIntrinsic(intr_id, *call_inst)) {
395 inst_iter->replaceAllUsesWith(new_value);
396 }
397
398 // Remove the old intrinsic call instruction
399 llvm::BasicBlock::iterator old_inst = inst_iter++;
400 old_inst->eraseFromParent();
401
402 // Splice the instruction to the new basic block
403 llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
404 if (next_basic_block != curr_basic_block) {
405 next_basic_block->getInstList().splice(
406 irb_.GetInsertPoint(), curr_basic_block->getInstList(),
407 inst_iter, inst_end);
408 curr_basic_block = next_basic_block;
409 inst_end = curr_basic_block->end();
410 }
411 }
412}
413
414
415void GBCExpanderPass::RewriteFunction() {
416 size_t num_basic_blocks = func_->getBasicBlockList().size();
417 // NOTE: We are not using (bb_iter != bb_end) as the for-loop condition,
418 // because we will create new basic block while expanding the intrinsics.
419 // We only want to iterate through the input basic blocks.
420
421 for (llvm::Function::iterator bb_iter = func_->begin();
422 num_basic_blocks > 0; ++bb_iter, --num_basic_blocks) {
423
424 // Rewrite the basic block
425 RewriteBasicBlock(bb_iter);
426
427 // Update the phi-instructions in the successor basic block
428 llvm::BasicBlock* last_block = irb_.GetInsertBlock();
429 if (last_block != bb_iter) {
430 UpdatePhiInstruction(bb_iter, last_block);
431 }
432 }
433}
434
435void GBCExpanderPass::UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
436 llvm::BasicBlock* new_basic_block) {
437 llvm::TerminatorInst* term_inst = new_basic_block->getTerminator();
438
439 if (!term_inst) {
440 return; // No terminating instruction in new_basic_block. Nothing to do.
441 }
442
443 // Iterate every succeeding basic block
444 for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
445 succ_iter != succ_end; ++succ_iter) {
446 llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
447
448 // Iterate every phi instructions in the succeeding basic block
449 for (llvm::BasicBlock::iterator
450 inst_iter = succ_basic_block->begin(),
451 inst_end = succ_basic_block->end();
452 inst_iter != inst_end; ++inst_iter) {
453 llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
454
455 if (!phi) {
456 break; // Meet non-phi instruction. Done.
457 }
458
459 // Update the incoming block of this phi instruction
460 for (llvm::PHINode::block_iterator
461 ibb_iter = phi->block_begin(), ibb_end = phi->block_end();
462 ibb_iter != ibb_end; ++ibb_iter) {
463 if (*ibb_iter == old_basic_block) {
464 *ibb_iter = new_basic_block;
465 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700466 }
467 }
468 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700469}
470
471llvm::Value* GBCExpanderPass::ExpandToRuntime(runtime_support::RuntimeId rt,
472 llvm::CallInst& inst) {
473 // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
474 // the arguments passed to the GBC intrinsic are as the same as IBC runtime
475 // function, therefore only called function is needed to change.
476 unsigned num_args = inst.getNumArgOperands();
477
478 if (num_args <= 0) {
479 return irb_.CreateCall(irb_.GetRuntime(rt));
480 } else {
481 std::vector<llvm::Value*> args;
482 for (unsigned i = 0; i < num_args; i++) {
483 args.push_back(inst.getArgOperand(i));
484 }
485
486 return irb_.CreateCall(irb_.GetRuntime(rt), args);
487 }
488}
489
Logan Chien67645d82012-08-17 09:10:54 +0800490void
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700491GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
492 llvm::Function* func = first_non_alloca->getParent()->getParent();
493 llvm::Module* module = func->getParent();
494
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700495 // Call llvm intrinsic function to get frame address.
496 llvm::Function* frameaddress =
497 llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
498
499 // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
500 llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
501
502 // Cast i8* to int
503 frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
504
505 // Get thread.stack_end_
506 llvm::Value* stack_end =
507 irb_.Runtime().EmitLoadFromThreadOffset(Thread::StackEndOffset().Int32Value(),
508 irb_.getPtrEquivIntTy(),
509 kTBAARuntimeInfo);
510
511 // Check the frame address < thread.stack_end_ ?
512 llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
513
514 llvm::BasicBlock* block_exception =
515 llvm::BasicBlock::Create(context_, "stack_overflow", func);
516
517 llvm::BasicBlock* block_continue =
518 llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
519
520 irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
521
522 // If stack overflow, throw exception.
523 irb_.SetInsertPoint(block_exception);
524 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowStackOverflowException));
525
526 // Unwind.
527 llvm::Type* ret_type = func->getReturnType();
528 if (ret_type->isVoidTy()) {
529 irb_.CreateRetVoid();
530 } else {
531 // The return value is ignored when there's an exception. MethodCompiler
532 // returns zero value under the the corresponding return type in this case.
533 // GBCExpander returns LLVM undef value here for brevity
534 irb_.CreateRet(llvm::UndefValue::get(ret_type));
535 }
536
537 irb_.SetInsertPoint(block_continue);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700538}
539
540llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(MemberOffset offset) {
541 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
542
543 return irb_.LoadFromObjectOffset(method_object_addr,
544 offset.Int32Value(),
545 irb_.getJObjectTy(),
546 kTBAAConstJObject);
547}
548
549llvm::Value*
550GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
551 llvm::Value* static_storage_dex_cache_addr =
552 EmitLoadDexCacheAddr(Method::DexCacheInitializedStaticStorageOffset());
553
554 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
555
556 return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
557}
558
559llvm::Value*
560GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
561 llvm::Value* resolved_type_dex_cache_addr =
562 EmitLoadDexCacheAddr(Method::DexCacheResolvedTypesOffset());
563
564 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
565
566 return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
567}
568
569llvm::Value* GBCExpanderPass::
570EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
571 llvm::Value* resolved_method_dex_cache_addr =
572 EmitLoadDexCacheAddr(Method::DexCacheResolvedMethodsOffset());
573
574 llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
575
576 return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
577}
578
579llvm::Value* GBCExpanderPass::
580EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
581 llvm::Value* string_dex_cache_addr =
582 EmitLoadDexCacheAddr(Method::DexCacheStringsOffset());
583
584 llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
585
586 return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
587}
588
589llvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
590 llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
591 return parent_func->arg_begin();
592}
593
594llvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
595 // Load array length
596 return irb_.LoadFromObjectOffset(array,
597 Array::LengthOffset().Int32Value(),
598 irb_.getJIntTy(),
599 kTBAAConstJObject);
600
601}
602
603llvm::Value*
604GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
605 llvm::Value* callee_method_object_field_addr =
606 EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
607
608 return irb_.CreateLoad(callee_method_object_field_addr, kTBAAJRuntime);
609}
610
611llvm::Value* GBCExpanderPass::
612EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
613 // Load class object of *this* pointer
614 llvm::Value* class_object_addr =
615 irb_.LoadFromObjectOffset(this_addr,
616 Object::ClassOffset().Int32Value(),
617 irb_.getJObjectTy(),
618 kTBAAConstJObject);
619
620 // Load vtable address
621 llvm::Value* vtable_addr =
622 irb_.LoadFromObjectOffset(class_object_addr,
623 Class::VTableOffset().Int32Value(),
624 irb_.getJObjectTy(),
625 kTBAAConstJObject);
626
627 // Load callee method object
628 llvm::Value* vtable_idx_value =
629 irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
630
631 llvm::Value* method_field_addr =
632 EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
633
634 return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
635}
636
637// Emit Array GetElementPtr
638llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
639 llvm::Value* index_value,
640 JType elem_jty) {
641
642 int data_offset;
643 if (elem_jty == kLong || elem_jty == kDouble ||
644 (elem_jty == kObject && sizeof(uint64_t) == sizeof(Object*))) {
645 data_offset = Array::DataOffset(sizeof(int64_t)).Int32Value();
646 } else {
647 data_offset = Array::DataOffset(sizeof(int32_t)).Int32Value();
648 }
649
650 llvm::Constant* data_offset_value =
651 irb_.getPtrEquivInt(data_offset);
652
653 llvm::Type* elem_type = irb_.getJType(elem_jty, kArray);
654
655 llvm::Value* array_data_addr =
656 irb_.CreatePtrDisp(array_addr, data_offset_value,
657 elem_type->getPointerTo());
658
659 return irb_.CreateGEP(array_data_addr, index_value);
660}
661
662void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700663 irb_.Runtime().EmitTestSuspend();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700664 return;
665}
666
TDYa1279a129452012-07-19 03:10:08 -0700667void GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
TDYa1279a129452012-07-19 03:10:08 -0700668 irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
TDYa1279a129452012-07-19 03:10:08 -0700669 return;
670}
671
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700672llvm::Value* GBCExpanderPass::Expand_GetException() {
673 // Get thread-local exception field address
674 llvm::Value* exception_object_addr =
675 irb_.Runtime().EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
676 irb_.getJObjectTy(),
677 kTBAAJRuntime);
678
679 // Set thread-local exception field address to NULL
680 irb_.Runtime().EmitStoreToThreadOffset(Thread::ExceptionOffset().Int32Value(),
681 irb_.getJNull(),
682 kTBAAJRuntime);
683
684 return exception_object_addr;
685}
686
687llvm::Value*
688GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
689 uint32_t string_idx =
690 llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
691
692 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
693
694 return irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
695}
696
697llvm::Value*
698GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
699 uint32_t type_idx =
700 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
701
702 llvm::Value* type_field_addr =
703 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
704
705 return irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
706}
707
708void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700709 rtb_.EmitLockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700710 return;
711}
712
713void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700714 rtb_.EmitUnlockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700715 return;
716}
717
718llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
719 llvm::Value* index_value,
720 JType elem_jty) {
721 llvm::Value* array_elem_addr =
722 EmitArrayGEP(array_addr, index_value, elem_jty);
723
724 return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
725}
726
727void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
728 llvm::Value* array_addr,
729 llvm::Value* index_value,
730 JType elem_jty) {
731 llvm::Value* array_elem_addr =
732 EmitArrayGEP(array_addr, index_value, elem_jty);
733
734 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
735
736 return;
737}
738
739void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
740 // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
741 llvm::Value* array = call_inst.getArgOperand(0);
742
743 uint32_t element_jty =
744 llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
745
746 DCHECK(call_inst.getNumArgOperands() > 2);
747 unsigned num_elements = (call_inst.getNumArgOperands() - 2);
748
749 bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
750
751 uint32_t alignment;
752 llvm::Constant* elem_size;
753 llvm::PointerType* field_type;
754
755 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
756 // as the element, thus we are only checking 2 cases: primitive int and
757 // non-primitive type.
758 if (is_elem_int_ty) {
759 alignment = sizeof(int32_t);
760 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
761 field_type = irb_.getJIntTy()->getPointerTo();
762 } else {
763 alignment = irb_.getSizeOfPtrEquivInt();
764 elem_size = irb_.getSizeOfPtrEquivIntValue();
765 field_type = irb_.getJObjectTy()->getPointerTo();
766 }
767
768 llvm::Value* data_field_offset =
769 irb_.getPtrEquivInt(Array::DataOffset(alignment).Int32Value());
770
771 llvm::Value* data_field_addr =
772 irb_.CreatePtrDisp(array, data_field_offset, field_type);
773
774 for (unsigned i = 0; i < num_elements; ++i) {
775 // Values to fill the array begin at the 3rd argument
776 llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
777
778 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
779
780 data_field_addr =
781 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
782 }
783
784 return;
785}
786
787llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
788 llvm::Value* /*is_volatile_value*/,
789 llvm::Value* object_addr,
790 JType field_jty) {
791 int field_offset =
792 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
793
794 DCHECK_GE(field_offset, 0);
795
796 llvm::PointerType* field_type =
797 irb_.getJType(field_jty, kField)->getPointerTo();
798
799 field_offset_value = irb_.getPtrEquivInt(field_offset);
800
801 llvm::Value* field_addr =
802 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
803
804 // TODO: Check is_volatile. We need to generate atomic load instruction
805 // when is_volatile is true.
806 return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
807}
808
809void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
810 llvm::Value* /* is_volatile_value */,
811 llvm::Value* object_addr,
812 llvm::Value* new_value,
813 JType field_jty) {
814 int field_offset =
815 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
816
817 DCHECK_GE(field_offset, 0);
818
819 llvm::PointerType* field_type =
820 irb_.getJType(field_jty, kField)->getPointerTo();
821
822 field_offset_value = irb_.getPtrEquivInt(field_offset);
823
824 llvm::Value* field_addr =
825 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
826
827 // TODO: Check is_volatile. We need to generate atomic store instruction
828 // when is_volatile is true.
829 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
830
831 return;
832}
833
834llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
835 llvm::Value* field_offset_value,
836 llvm::Value* /*is_volatile_value*/,
837 JType field_jty) {
838 int field_offset =
839 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
840
841 DCHECK_GE(field_offset, 0);
842
843 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
844
845 llvm::Value* static_field_addr =
846 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
847 irb_.getJType(field_jty, kField)->getPointerTo());
848
849 // TODO: Check is_volatile. We need to generate atomic store instruction
850 // when is_volatile is true.
851 return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
852}
853
854void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
855 llvm::Value* field_offset_value,
856 llvm::Value* /* is_volatile_value */,
857 llvm::Value* new_value,
858 JType field_jty) {
859 int field_offset =
860 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
861
862 DCHECK_GE(field_offset, 0);
863
864 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
865
866 llvm::Value* static_field_addr =
867 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
868 irb_.getJType(field_jty, kField)->getPointerTo());
869
870 // TODO: Check is_volatile. We need to generate atomic store instruction
871 // when is_volatile is true.
872 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
873
874 return;
875}
876
877llvm::Value*
878GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
879 return irb_.LoadFromObjectOffset(method_object_addr,
880 Method::DeclaringClassOffset().Int32Value(),
881 irb_.getJObjectTy(),
882 kTBAAConstJObject);
883}
884
885llvm::Value*
886GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
887 uint32_t type_idx =
888 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
889
890 llvm::Value* storage_field_addr =
891 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
892
893 return irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
894}
895
896llvm::Value*
897GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
898 uint32_t callee_method_idx =
899 llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
900
901 return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
902}
903
904llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
905 llvm::Value* vtable_idx_value,
906 llvm::Value* this_addr) {
907 int vtable_idx =
908 llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
909
910 return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
911}
912
913llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
914 // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
915 llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
916 unsigned num_args = call_inst.getNumArgOperands();
917 llvm::Type* ret_type = call_inst.getType();
918
919 // Determine the function type of the callee method
920 std::vector<llvm::Type*> args_type;
921 std::vector<llvm::Value*> args;
922 for (unsigned i = 0; i < num_args; i++) {
923 args.push_back(call_inst.getArgOperand(i));
924 args_type.push_back(args[i]->getType());
925 }
926
927 llvm::FunctionType* callee_method_type =
928 llvm::FunctionType::get(ret_type, args_type, false);
929
930 llvm::Value* code_addr =
931 irb_.LoadFromObjectOffset(callee_method_object_addr,
932 Method::GetCodeOffset().Int32Value(),
933 callee_method_type->getPointerTo(),
934 kTBAAJRuntime);
935
936 // Invoke callee
937 llvm::Value* retval = irb_.CreateCall(code_addr, args);
938
939 return retval;
940}
941
TDYa1274ec8ccd2012-08-11 07:04:57 -0700942llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::CallInst& call_inst,
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700943 bool is_div, JType op_jty) {
TDYa1274ec8ccd2012-08-11 07:04:57 -0700944 llvm::Value* dividend = call_inst.getArgOperand(0);
945 llvm::Value* divisor = call_inst.getArgOperand(1);
946#if defined(ART_USE_QUICK_COMPILER)
947 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
948 EmitGuard_DivZeroException(dex_pc, divisor, op_jty);
949#endif
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700950 // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
951
952 // Check the special case: MININT / -1 = MININT
953 // That case will cause overflow, which is undefined behavior in llvm.
954 // So we check the divisor is -1 or not, if the divisor is -1, we do
955 // the special path to avoid undefined behavior.
956 llvm::Type* op_type = irb_.getJType(op_jty, kAccurate);
957 llvm::Value* zero = irb_.getJZero(op_jty);
958 llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
959
TDYa1275e869b62012-07-25 00:45:39 -0700960 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700961 llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
962 llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
963 llvm::BasicBlock* neg_one_cont =
964 llvm::BasicBlock::Create(context_, "", parent);
965
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700966 llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
967 irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
968
969 // If divisor == -1
970 irb_.SetInsertPoint(eq_neg_one);
971 llvm::Value* eq_result;
972 if (is_div) {
973 // We can just change from "dividend div -1" to "neg dividend". The sub
974 // don't care the sign/unsigned because of two's complement representation.
975 // And the behavior is what we want:
976 // -(2^n) (2^n)-1
977 // MININT < k <= MAXINT -> mul k -1 = -k
978 // MININT == k -> mul k -1 = k
979 //
980 // LLVM use sub to represent 'neg'
981 eq_result = irb_.CreateSub(zero, dividend);
982 } else {
983 // Everything modulo -1 will be 0.
984 eq_result = zero;
985 }
986 irb_.CreateBr(neg_one_cont);
987
988 // If divisor != -1, just do the division.
989 irb_.SetInsertPoint(ne_neg_one);
990 llvm::Value* ne_result;
991 if (is_div) {
992 ne_result = irb_.CreateSDiv(dividend, divisor);
993 } else {
994 ne_result = irb_.CreateSRem(dividend, divisor);
995 }
996 irb_.CreateBr(neg_one_cont);
997
998 irb_.SetInsertPoint(neg_one_cont);
999 llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
1000 result->addIncoming(eq_result, eq_neg_one);
1001 result->addIncoming(ne_result, ne_neg_one);
1002
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001003 return result;
1004}
1005
1006void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value) {
1007 // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
1008 // MethodCompiler::EmitPushShadowFrame
1009 shadow_frame_size_ =
1010 llvm::cast<llvm::ConstantInt>(num_entry_value)->getZExtValue();
1011
1012 llvm::StructType* shadow_frame_type =
1013 irb_.getShadowFrameTy(shadow_frame_size_);
1014
1015 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
1016
1017 // Alloca a pointer to old shadow frame
1018 old_shadow_frame_ =
1019 irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
1020
1021 // Zero-initialization of the shadow frame table
1022 llvm::Value* shadow_frame_table =
1023 irb_.CreateConstGEP2_32(shadow_frame_, 0, 1);
1024 llvm::Type* table_type = shadow_frame_type->getElementType(1);
1025
1026 llvm::ConstantAggregateZero* zero_initializer =
1027 llvm::ConstantAggregateZero::get(table_type);
1028
1029 irb_.CreateStore(zero_initializer, shadow_frame_table, kTBAAShadowFrame);
1030
1031 // Push the shadow frame
1032 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1033
1034 // Push the shadow frame
1035 llvm::Value* shadow_frame_upcast =
1036 irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
1037
1038 llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
1039 method_object_addr,
1040 shadow_frame_size_);
1041
1042 irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
1043
1044 return;
1045}
1046
1047void GBCExpanderPass::Expand_SetShadowFrameEntry(llvm::Value* obj,
1048 llvm::Value* entry_idx) {
1049 DCHECK(shadow_frame_ != NULL);
1050
1051 llvm::Value* gep_index[] = {
1052 irb_.getInt32(0), // No pointer displacement
1053 irb_.getInt32(1), // SIRT
1054 entry_idx // Pointer field
1055 };
1056
1057 llvm::Value* entry_addr = irb_.CreateGEP(shadow_frame_, gep_index);
1058 irb_.CreateStore(obj, entry_addr, kTBAAShadowFrame);
1059 return;
1060}
1061
1062void GBCExpanderPass::Expand_PopShadowFrame() {
1063 rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
1064 return;
1065}
1066
1067void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
1068 irb_.StoreToObjectOffset(shadow_frame_,
1069 ShadowFrame::DexPCOffset(),
1070 dex_pc_value,
1071 kTBAAShadowFrame);
1072 return;
1073}
1074
Logan Chien67645d82012-08-17 09:10:54 +08001075void GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001076 // DexLang generates all alloca instruction in the first basic block of the
1077 // FUNC and also there's no any alloca instructions after the first non-alloca
1078 // instruction
1079
Logan Chien67645d82012-08-17 09:10:54 +08001080 llvm::BasicBlock* first_basic_block = &func.front();
1081
1082 // Look for first non-alloca instruction
1083 llvm::BasicBlock::iterator first_non_alloca = first_basic_block->begin();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001084 while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
1085 ++first_non_alloca;
1086 }
1087
Logan Chien67645d82012-08-17 09:10:54 +08001088 irb_.SetInsertPoint(first_non_alloca);
1089
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001090 // Insert stack overflow check codes before first_non_alloca (i.e., after all
1091 // alloca instructions)
Logan Chien67645d82012-08-17 09:10:54 +08001092 EmitStackOverflowCheck(&*first_non_alloca);
1093
1094 llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
1095 if (next_basic_block != first_basic_block) {
1096 // Splice the rest of the instruction to the continuing basic block
1097 next_basic_block->getInstList().splice(
1098 irb_.GetInsertPoint(), first_basic_block->getInstList(),
1099 first_non_alloca, first_basic_block->end());
1100
1101 // Rewrite the basic block
1102 RewriteBasicBlock(next_basic_block);
1103
1104 // Update the phi-instructions in the successor basic block
1105 UpdatePhiInstruction(first_basic_block, irb_.GetInsertBlock());
1106 }
1107
1108 // We have changed the basic block
1109 changed_ = true;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001110}
1111
TDYa1275e869b62012-07-25 00:45:39 -07001112// ==== High-level intrinsic expander ==========================================
1113
TDYa127a1b21852012-07-23 03:20:39 -07001114llvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
1115 llvm::Value* src2_value,
1116 bool gt_bias) {
1117 llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
1118 llvm::Value* cmp_lt;
1119
1120 if (gt_bias) {
1121 cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
1122 } else {
1123 cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
1124 }
1125
1126 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1127}
1128
1129llvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
1130 llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
1131 llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
1132
1133 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1134}
1135
1136llvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
1137 llvm::Value* cmp_lt) {
1138
1139 llvm::Constant* zero = irb_.getJInt(0);
1140 llvm::Constant* pos1 = irb_.getJInt(1);
1141 llvm::Constant* neg1 = irb_.getJInt(-1);
1142
1143 llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
1144 llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
1145
1146 return result_eq;
1147}
1148
Logan Chien75e4b602012-07-23 14:24:12 -07001149llvm::Value* GBCExpanderPass::Expand_IntegerShift(llvm::Value* src1_value,
1150 llvm::Value* src2_value,
1151 IntegerShiftKind kind,
1152 JType op_jty) {
1153 DCHECK(op_jty == kInt || op_jty == kLong);
1154
1155 // Mask and zero-extend RHS properly
1156 if (op_jty == kInt) {
1157 src2_value = irb_.CreateAnd(src2_value, 0x1f);
1158 } else {
1159 llvm::Value* masked_src2_value = irb_.CreateAnd(src2_value, 0x3f);
1160 src2_value = irb_.CreateZExt(masked_src2_value, irb_.getJLongTy());
1161 }
1162
1163 // Create integer shift llvm instruction
1164 switch (kind) {
1165 case kIntegerSHL:
1166 return irb_.CreateShl(src1_value, src2_value);
1167
1168 case kIntegerSHR:
1169 return irb_.CreateAShr(src1_value, src2_value);
1170
1171 case kIntegerUSHR:
1172 return irb_.CreateLShr(src1_value, src2_value);
1173
1174 default:
1175 LOG(FATAL) << "Unknown integer shift kind: " << kind;
1176 return NULL;
1177 }
1178}
1179
TDYa1275a26d442012-07-26 18:58:38 -07001180llvm::Value* GBCExpanderPass::Expand_HLArrayGet(llvm::CallInst& call_inst,
1181 JType elem_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001182 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1183 llvm::Value* array_addr = call_inst.getArgOperand(1);
1184 llvm::Value* index_value = call_inst.getArgOperand(2);
1185
1186 // TODO: opt_flags
1187 EmitGuard_ArrayException(dex_pc, array_addr, index_value);
1188
1189 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1190
1191 llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
1192
1193 switch (elem_jty) {
1194 case kVoid:
1195 break;
1196
1197 case kBoolean:
1198 case kChar:
1199 array_elem_value = irb_.CreateZExt(array_elem_value, irb_.getJType(elem_jty, kReg));
1200 break;
1201
1202 case kByte:
1203 case kShort:
1204 array_elem_value = irb_.CreateSExt(array_elem_value, irb_.getJType(elem_jty, kReg));
1205 break;
1206
1207 case kInt:
1208 case kLong:
1209 case kFloat:
1210 case kDouble:
1211 case kObject:
1212 break;
1213
1214 default:
1215 LOG(FATAL) << "Unknown java type: " << elem_jty;
1216 }
1217
1218 return array_elem_value;
1219}
1220
1221
1222void GBCExpanderPass::Expand_HLArrayPut(llvm::CallInst& call_inst,
1223 JType elem_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001224 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1225 llvm::Value* new_value = call_inst.getArgOperand(1);
1226 llvm::Value* array_addr = call_inst.getArgOperand(2);
1227 llvm::Value* index_value = call_inst.getArgOperand(3);
1228
1229 // TODO: opt_flags
1230 EmitGuard_ArrayException(dex_pc, array_addr, index_value);
1231
1232 switch (elem_jty) {
1233 case kVoid:
1234 break;
1235
1236 case kBoolean:
1237 case kChar:
1238 new_value = irb_.CreateTrunc(new_value, irb_.getJType(elem_jty, kArray));
1239 break;
1240
1241 case kInt:
1242 case kLong:
1243 case kFloat:
1244 case kDouble:
1245 case kObject:
1246 break;
1247
1248 default:
1249 LOG(FATAL) << "Unknown java type: " << elem_jty;
1250 }
1251
1252 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1253
1254 if (elem_jty == kObject) { // If put an object, check the type, and mark GC card table.
1255 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::CheckPutArrayElement);
1256
1257 irb_.CreateCall2(runtime_func, new_value, array_addr);
1258
1259 EmitGuard_ExceptionLandingPad(dex_pc);
1260
1261 EmitMarkGCCard(new_value, array_addr);
1262 }
1263
1264 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
1265
1266 return;
1267}
1268
TDYa1275e869b62012-07-25 00:45:39 -07001269llvm::Value* GBCExpanderPass::Expand_HLIGet(llvm::CallInst& call_inst,
1270 JType field_jty) {
TDYa1275e869b62012-07-25 00:45:39 -07001271 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1272 llvm::Value* object_addr = call_inst.getArgOperand(1);
1273 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(2));
1274
1275 // TODO: opt_flags
1276 EmitGuard_NullPointerException(dex_pc, object_addr);
1277
1278 llvm::Value* field_value;
1279
1280 int field_offset;
1281 bool is_volatile;
1282 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1283 field_idx, oat_compilation_unit_, field_offset, is_volatile, false);
1284
1285 if (!is_fast_path) {
1286 llvm::Function* runtime_func;
1287
1288 if (field_jty == kObject) {
1289 runtime_func = irb_.GetRuntime(runtime_support::GetObjectInstance);
1290 } else if (field_jty == kLong || field_jty == kDouble) {
1291 runtime_func = irb_.GetRuntime(runtime_support::Get64Instance);
1292 } else {
1293 runtime_func = irb_.GetRuntime(runtime_support::Get32Instance);
1294 }
1295
1296 llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
1297
1298 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1299
1300 EmitUpdateDexPC(dex_pc);
1301
1302 field_value = irb_.CreateCall3(runtime_func, field_idx_value,
1303 method_object_addr, object_addr);
1304
1305 EmitGuard_ExceptionLandingPad(dex_pc);
1306
1307 } else {
1308 DCHECK_GE(field_offset, 0);
1309
1310 llvm::PointerType* field_type =
1311 irb_.getJType(field_jty, kField)->getPointerTo();
1312
1313 llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
1314
1315 llvm::Value* field_addr =
1316 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1317
1318 // TODO: Check is_volatile. We need to generate atomic load instruction
1319 // when is_volatile is true.
1320 field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
1321 }
1322
1323 if (field_jty == kFloat || field_jty == kDouble) {
TDYa1275a26d442012-07-26 18:58:38 -07001324 field_value = irb_.CreateBitCast(field_value, irb_.getJType(field_jty, kAccurate));
TDYa1275e869b62012-07-25 00:45:39 -07001325 }
1326
1327 return field_value;
1328}
1329
1330void GBCExpanderPass::Expand_HLIPut(llvm::CallInst& call_inst,
1331 JType field_jty) {
TDYa1275e869b62012-07-25 00:45:39 -07001332 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1333 llvm::Value* object_addr = call_inst.getArgOperand(1);
1334 llvm::Value* new_value = call_inst.getArgOperand(2);
1335 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(3));
1336
1337 if (field_jty == kFloat || field_jty == kDouble) {
TDYa1275a26d442012-07-26 18:58:38 -07001338 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty, kField));
TDYa1275e869b62012-07-25 00:45:39 -07001339 }
1340
1341 // TODO: opt_flags
1342 EmitGuard_NullPointerException(dex_pc, object_addr);
1343
1344 int field_offset;
1345 bool is_volatile;
1346 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1347 field_idx, oat_compilation_unit_, field_offset, is_volatile, true);
1348
1349 if (!is_fast_path) {
1350 llvm::Function* runtime_func;
1351
1352 if (field_jty == kObject) {
1353 runtime_func = irb_.GetRuntime(runtime_support::SetObjectInstance);
1354 } else if (field_jty == kLong || field_jty == kDouble) {
1355 runtime_func = irb_.GetRuntime(runtime_support::Set64Instance);
1356 } else {
1357 runtime_func = irb_.GetRuntime(runtime_support::Set32Instance);
1358 }
1359
1360 llvm::Value* field_idx_value = irb_.getInt32(field_idx);
1361
1362 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1363
1364 EmitUpdateDexPC(dex_pc);
1365
1366 irb_.CreateCall4(runtime_func, field_idx_value,
1367 method_object_addr, object_addr, new_value);
1368
1369 EmitGuard_ExceptionLandingPad(dex_pc);
1370
1371 } else {
1372 DCHECK_GE(field_offset, 0);
1373
1374 llvm::PointerType* field_type =
1375 irb_.getJType(field_jty, kField)->getPointerTo();
1376
1377 llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
1378
1379 llvm::Value* field_addr =
1380 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1381
1382 // TODO: Check is_volatile. We need to generate atomic store instruction
1383 // when is_volatile is true.
1384 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
1385
1386 if (field_jty == kObject) { // If put an object, mark the GC card table.
1387 EmitMarkGCCard(new_value, object_addr);
1388 }
1389 }
1390
1391 return;
1392}
1393
TDYa127f71bf5a2012-07-29 20:09:52 -07001394llvm::Value* GBCExpanderPass::EmitLoadConstantClass(uint32_t dex_pc,
1395 uint32_t type_idx) {
1396 if (!compiler_->CanAccessTypeWithoutChecks(method_idx_, dex_cache_,
1397 *dex_file_, type_idx)) {
1398 llvm::Value* type_idx_value = irb_.getInt32(type_idx);
1399
1400 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1401
1402 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1403
1404 llvm::Function* runtime_func =
1405 irb_.GetRuntime(runtime_support::InitializeTypeAndVerifyAccess);
1406
1407 EmitUpdateDexPC(dex_pc);
1408
1409 llvm::Value* type_object_addr =
1410 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1411
1412 EmitGuard_ExceptionLandingPad(dex_pc);
1413
1414 return type_object_addr;
1415
1416 } else {
1417 // Try to load the class (type) object from the test cache.
1418 llvm::Value* type_field_addr =
1419 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
1420
1421 llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
1422
1423 if (compiler_->CanAssumeTypeIsPresentInDexCache(dex_cache_, type_idx)) {
1424 return type_object_addr;
1425 }
1426
1427 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1428
1429 // Test whether class (type) object is in the dex cache or not
1430 llvm::Value* equal_null =
1431 irb_.CreateICmpEQ(type_object_addr, irb_.getJNull());
1432
1433 llvm::BasicBlock* block_cont =
1434 CreateBasicBlockWithDexPC(dex_pc, "cont");
1435
1436 llvm::BasicBlock* block_load_class =
1437 CreateBasicBlockWithDexPC(dex_pc, "load_class");
1438
1439 irb_.CreateCondBr(equal_null, block_load_class, block_cont, kUnlikely);
1440
1441 // Failback routine to load the class object
1442 irb_.SetInsertPoint(block_load_class);
1443
1444 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeType);
1445
1446 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1447
1448 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1449
1450 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1451
1452 EmitUpdateDexPC(dex_pc);
1453
1454 llvm::Value* loaded_type_object_addr =
1455 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1456
1457 EmitGuard_ExceptionLandingPad(dex_pc);
1458
1459 llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
1460
1461 irb_.CreateBr(block_cont);
1462
1463 // Now the class object must be loaded
1464 irb_.SetInsertPoint(block_cont);
1465
1466 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1467
1468 phi->addIncoming(type_object_addr, block_original);
1469 phi->addIncoming(loaded_type_object_addr, block_after_load_class);
1470
1471 return phi;
1472 }
1473}
1474
TDYa1275a26d442012-07-26 18:58:38 -07001475llvm::Value* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc,
1476 uint32_t type_idx) {
1477 llvm::BasicBlock* block_load_static =
1478 CreateBasicBlockWithDexPC(dex_pc, "load_static");
1479
1480 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
1481
1482 // Load static storage from dex cache
1483 llvm::Value* storage_field_addr =
1484 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
1485
1486 llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
1487
1488 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1489
1490 // Test: Is the static storage of this class initialized?
1491 llvm::Value* equal_null =
1492 irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
1493
1494 irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely);
1495
1496 // Failback routine to load the class object
1497 irb_.SetInsertPoint(block_load_static);
1498
1499 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeStaticStorage);
1500
1501 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1502
1503 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1504
1505 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1506
1507 EmitUpdateDexPC(dex_pc);
1508
1509 llvm::Value* loaded_storage_object_addr =
1510 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1511
1512 EmitGuard_ExceptionLandingPad(dex_pc);
1513
1514 llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
1515
1516 irb_.CreateBr(block_cont);
1517
1518 // Now the class object must be loaded
1519 irb_.SetInsertPoint(block_cont);
1520
1521 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1522
1523 phi->addIncoming(storage_object_addr, block_original);
1524 phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
1525
1526 return phi;
1527}
1528
1529llvm::Value* GBCExpanderPass::Expand_HLSget(llvm::CallInst& call_inst,
1530 JType field_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001531 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1532 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1533
1534 int field_offset;
1535 int ssb_index;
1536 bool is_referrers_class;
1537 bool is_volatile;
1538
1539 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
1540 field_idx, oat_compilation_unit_, field_offset, ssb_index,
1541 is_referrers_class, is_volatile, false);
1542
1543 llvm::Value* static_field_value;
1544
1545 if (!is_fast_path) {
1546 llvm::Function* runtime_func;
1547
1548 if (field_jty == kObject) {
1549 runtime_func = irb_.GetRuntime(runtime_support::GetObjectStatic);
1550 } else if (field_jty == kLong || field_jty == kDouble) {
1551 runtime_func = irb_.GetRuntime(runtime_support::Get64Static);
1552 } else {
1553 runtime_func = irb_.GetRuntime(runtime_support::Get32Static);
1554 }
1555
1556 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1557
1558 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1559
1560 EmitUpdateDexPC(dex_pc);
1561
1562 static_field_value =
1563 irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
1564
1565 EmitGuard_ExceptionLandingPad(dex_pc);
1566
1567 } else {
1568 DCHECK_GE(field_offset, 0);
1569
1570 llvm::Value* static_storage_addr = NULL;
1571
1572 if (is_referrers_class) {
1573 // Fast path, static storage base is this method's class
1574 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1575
1576 static_storage_addr =
1577 irb_.LoadFromObjectOffset(method_object_addr,
1578 Method::DeclaringClassOffset().Int32Value(),
1579 irb_.getJObjectTy(),
1580 kTBAAConstJObject);
1581 } else {
1582 // Medium path, static storage base in a different class which
1583 // requires checks that the other class is initialized
1584 DCHECK_GE(ssb_index, 0);
1585 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1586 }
1587
1588 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1589
1590 llvm::Value* static_field_addr =
1591 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
1592 irb_.getJType(field_jty, kField)->getPointerTo());
1593
1594 // TODO: Check is_volatile. We need to generate atomic load instruction
1595 // when is_volatile is true.
1596 static_field_value = irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
1597 }
1598
1599 if (field_jty == kFloat || field_jty == kDouble) {
1600 static_field_value =
1601 irb_.CreateBitCast(static_field_value, irb_.getJType(field_jty, kAccurate));
1602 }
1603
1604 return static_field_value;
1605}
1606
1607void GBCExpanderPass::Expand_HLSput(llvm::CallInst& call_inst,
1608 JType field_jty) {
TDYa1275a26d442012-07-26 18:58:38 -07001609 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1610 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1611 llvm::Value* new_value = call_inst.getArgOperand(1);
1612
1613 if (field_jty == kFloat || field_jty == kDouble) {
1614 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty, kField));
1615 }
1616
1617 int field_offset;
1618 int ssb_index;
1619 bool is_referrers_class;
1620 bool is_volatile;
1621
1622 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
1623 field_idx, oat_compilation_unit_, field_offset, ssb_index,
1624 is_referrers_class, is_volatile, true);
1625
1626 if (!is_fast_path) {
1627 llvm::Function* runtime_func;
1628
1629 if (field_jty == kObject) {
1630 runtime_func = irb_.GetRuntime(runtime_support::SetObjectStatic);
1631 } else if (field_jty == kLong || field_jty == kDouble) {
1632 runtime_func = irb_.GetRuntime(runtime_support::Set64Static);
1633 } else {
1634 runtime_func = irb_.GetRuntime(runtime_support::Set32Static);
1635 }
1636
1637 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1638
1639 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1640
1641 EmitUpdateDexPC(dex_pc);
1642
1643 irb_.CreateCall3(runtime_func, field_idx_value,
1644 method_object_addr, new_value);
1645
1646 EmitGuard_ExceptionLandingPad(dex_pc);
1647
1648 } else {
1649 DCHECK_GE(field_offset, 0);
1650
1651 llvm::Value* static_storage_addr = NULL;
1652
1653 if (is_referrers_class) {
1654 // Fast path, static storage base is this method's class
1655 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1656
1657 static_storage_addr =
1658 irb_.LoadFromObjectOffset(method_object_addr,
1659 Method::DeclaringClassOffset().Int32Value(),
1660 irb_.getJObjectTy(),
1661 kTBAAConstJObject);
1662 } else {
1663 // Medium path, static storage base in a different class which
1664 // requires checks that the other class is initialized
1665 DCHECK_GE(ssb_index, 0);
1666 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1667 }
1668
1669 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1670
1671 llvm::Value* static_field_addr =
1672 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
1673 irb_.getJType(field_jty, kField)->getPointerTo());
1674
1675 // TODO: Check is_volatile. We need to generate atomic store instruction
1676 // when is_volatile is true.
1677 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
1678
1679 if (field_jty == kObject) { // If put an object, mark the GC card table.
1680 EmitMarkGCCard(new_value, static_storage_addr);
1681 }
1682 }
1683
1684 return;
1685}
1686
TDYa127f71bf5a2012-07-29 20:09:52 -07001687llvm::Value* GBCExpanderPass::Expand_ConstString(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001688 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1689 uint32_t string_idx = LV2UInt(call_inst.getArgOperand(0));
1690
1691 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
1692
1693 llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
1694
1695 if (!compiler_->CanAssumeStringIsPresentInDexCache(dex_cache_, string_idx)) {
1696 llvm::BasicBlock* block_str_exist =
1697 CreateBasicBlockWithDexPC(dex_pc, "str_exist");
1698
1699 llvm::BasicBlock* block_str_resolve =
1700 CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
1701
1702 llvm::BasicBlock* block_cont =
1703 CreateBasicBlockWithDexPC(dex_pc, "str_cont");
1704
1705 // Test: Is the string resolved and in the dex cache?
1706 llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.getJNull());
1707
1708 irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist, kUnlikely);
1709
1710 // String is resolved, go to next basic block.
1711 irb_.SetInsertPoint(block_str_exist);
1712 irb_.CreateBr(block_cont);
1713
1714 // String is not resolved yet, resolve it now.
1715 irb_.SetInsertPoint(block_str_resolve);
1716
1717 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::ResolveString);
1718
1719 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1720
1721 llvm::Value* string_idx_value = irb_.getInt32(string_idx);
1722
1723 EmitUpdateDexPC(dex_pc);
1724
1725 llvm::Value* result = irb_.CreateCall2(runtime_func, method_object_addr,
1726 string_idx_value);
1727
1728 EmitGuard_ExceptionLandingPad(dex_pc);
1729
1730 llvm::BasicBlock* block_pre_cont = irb_.GetInsertBlock();
1731
1732 irb_.SetInsertPoint(block_cont);
1733
1734 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1735
1736 phi->addIncoming(string_addr, block_str_exist);
1737 phi->addIncoming(result, block_pre_cont);
1738
1739 string_addr = phi;
1740 }
1741
1742 return string_addr;
1743}
1744
1745llvm::Value* GBCExpanderPass::Expand_ConstClass(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001746 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1747 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1748
1749 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
1750
1751 return type_object_addr;
1752}
1753
1754void GBCExpanderPass::Expand_MonitorEnter(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001755 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1756 llvm::Value* object_addr = call_inst.getArgOperand(1);
1757
1758 // TODO: opt_flags
1759 EmitGuard_NullPointerException(dex_pc, object_addr);
1760
1761 irb_.Runtime().EmitLockObject(object_addr);
1762
1763 return;
1764}
1765
1766void GBCExpanderPass::Expand_MonitorExit(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001767 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1768 llvm::Value* object_addr = call_inst.getArgOperand(1);
1769
1770 // TODO: opt_flags
1771 EmitGuard_NullPointerException(dex_pc, object_addr);
1772
1773 EmitUpdateDexPC(dex_pc);
1774
1775 irb_.Runtime().EmitUnlockObject(object_addr);
1776
1777 EmitGuard_ExceptionLandingPad(dex_pc);
1778
1779 return;
1780}
1781
1782void GBCExpanderPass::Expand_HLCheckCast(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001783 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1784 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1785 llvm::Value* object_addr = call_inst.getArgOperand(1);
1786
1787 llvm::BasicBlock* block_test_class =
1788 CreateBasicBlockWithDexPC(dex_pc, "test_class");
1789
1790 llvm::BasicBlock* block_test_sub_class =
1791 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
1792
1793 llvm::BasicBlock* block_cont =
1794 CreateBasicBlockWithDexPC(dex_pc, "checkcast_cont");
1795
1796 // Test: Is the reference equal to null? Act as no-op when it is null.
1797 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
1798
1799 irb_.CreateCondBr(equal_null,
1800 block_cont,
1801 block_test_class);
1802
1803 // Test: Is the object instantiated from the given class?
1804 irb_.SetInsertPoint(block_test_class);
1805 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
1806 DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
1807
1808 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
1809
1810 llvm::Value* object_type_field_addr =
1811 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
1812
1813 llvm::Value* object_type_object_addr =
1814 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
1815
1816 llvm::Value* equal_class =
1817 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
1818
1819 irb_.CreateCondBr(equal_class,
1820 block_cont,
1821 block_test_sub_class);
1822
1823 // Test: Is the object instantiated from the subclass of the given class?
1824 irb_.SetInsertPoint(block_test_sub_class);
1825
1826 EmitUpdateDexPC(dex_pc);
1827
1828 irb_.CreateCall2(irb_.GetRuntime(runtime_support::CheckCast),
1829 type_object_addr, object_type_object_addr);
1830
1831 EmitGuard_ExceptionLandingPad(dex_pc);
1832
1833 irb_.CreateBr(block_cont);
1834
1835 irb_.SetInsertPoint(block_cont);
1836
1837 return;
1838}
1839
1840llvm::Value* GBCExpanderPass::Expand_InstanceOf(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001841 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1842 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1843 llvm::Value* object_addr = call_inst.getArgOperand(1);
1844
1845 llvm::BasicBlock* block_nullp =
1846 CreateBasicBlockWithDexPC(dex_pc, "nullp");
1847
1848 llvm::BasicBlock* block_test_class =
1849 CreateBasicBlockWithDexPC(dex_pc, "test_class");
1850
1851 llvm::BasicBlock* block_class_equals =
1852 CreateBasicBlockWithDexPC(dex_pc, "class_eq");
1853
1854 llvm::BasicBlock* block_test_sub_class =
1855 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
1856
1857 llvm::BasicBlock* block_cont =
1858 CreateBasicBlockWithDexPC(dex_pc, "instance_of_cont");
1859
1860 // Overview of the following code :
1861 // We check for null, if so, then false, otherwise check for class == . If so
1862 // then true, otherwise do callout slowpath.
1863 //
1864 // Test: Is the reference equal to null? Set 0 when it is null.
1865 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
1866
1867 irb_.CreateCondBr(equal_null, block_nullp, block_test_class);
1868
1869 irb_.SetInsertPoint(block_nullp);
1870 irb_.CreateBr(block_cont);
1871
1872 // Test: Is the object instantiated from the given class?
1873 irb_.SetInsertPoint(block_test_class);
1874 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
1875 DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
1876
1877 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
1878
1879 llvm::Value* object_type_field_addr =
1880 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
1881
1882 llvm::Value* object_type_object_addr =
1883 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
1884
1885 llvm::Value* equal_class =
1886 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
1887
1888 irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class);
1889
1890 irb_.SetInsertPoint(block_class_equals);
1891 irb_.CreateBr(block_cont);
1892
1893 // Test: Is the object instantiated from the subclass of the given class?
1894 irb_.SetInsertPoint(block_test_sub_class);
1895 llvm::Value* result =
1896 irb_.CreateCall2(irb_.GetRuntime(runtime_support::IsAssignable),
1897 type_object_addr, object_type_object_addr);
1898 irb_.CreateBr(block_cont);
1899
1900 irb_.SetInsertPoint(block_cont);
1901
1902 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJIntTy(), 3);
1903
1904 phi->addIncoming(irb_.getJInt(0), block_nullp);
1905 phi->addIncoming(irb_.getJInt(1), block_class_equals);
1906 phi->addIncoming(result, block_test_sub_class);
1907
1908 return phi;
1909}
1910
1911llvm::Value* GBCExpanderPass::Expand_NewInstance(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001912 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1913 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1914
1915 llvm::Function* runtime_func;
1916 if (compiler_->CanAccessInstantiableTypeWithoutChecks(
1917 method_idx_, dex_cache_, *dex_file_, type_idx)) {
1918 runtime_func = irb_.GetRuntime(runtime_support::AllocObject);
1919 } else {
1920 runtime_func = irb_.GetRuntime(runtime_support::AllocObjectWithAccessCheck);
1921 }
1922
1923 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
1924
1925 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1926
1927 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1928
1929 EmitUpdateDexPC(dex_pc);
1930
1931 llvm::Value* object_addr =
1932 irb_.CreateCall3(runtime_func, type_index_value, method_object_addr, thread_object_addr);
1933
1934 EmitGuard_ExceptionLandingPad(dex_pc);
1935
1936 return object_addr;
1937}
1938
1939llvm::Value* GBCExpanderPass::Expand_HLInvoke(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07001940 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1941 InvokeType invoke_type = static_cast<InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
1942 bool is_static = (invoke_type == kStatic);
1943 uint32_t callee_method_idx = LV2UInt(call_inst.getArgOperand(1));
1944
1945 // Compute invoke related information for compiler decision
1946 int vtable_idx = -1;
1947 uintptr_t direct_code = 0;
1948 uintptr_t direct_method = 0;
1949 bool is_fast_path = compiler_->
1950 ComputeInvokeInfo(callee_method_idx, oat_compilation_unit_,
1951 invoke_type, vtable_idx, direct_code, direct_method);
1952
1953 // Load *this* actual parameter
1954 llvm::Value* this_addr = NULL;
1955
1956 if (!is_static) {
1957 // Test: Is *this* parameter equal to null?
1958 this_addr = call_inst.getArgOperand(3);
1959 }
1960
1961 // Load the method object
1962 llvm::Value* callee_method_object_addr = NULL;
1963
1964 if (!is_fast_path) {
1965 callee_method_object_addr =
1966 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx, invoke_type,
1967 this_addr, dex_pc, is_fast_path);
1968
1969 // TODO: opt_flags
1970 if (!is_static) {
1971 EmitGuard_NullPointerException(dex_pc, this_addr);
1972 }
1973 } else {
1974 // TODO: opt_flags
1975 if (!is_static) {
1976 EmitGuard_NullPointerException(dex_pc, this_addr);
1977 }
1978
1979 switch (invoke_type) {
1980 case kStatic:
1981 case kDirect:
1982 if (direct_method != 0u &&
1983 direct_method != static_cast<uintptr_t>(-1)) {
1984 callee_method_object_addr =
1985 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_method),
1986 irb_.getJObjectTy());
1987 } else {
1988 callee_method_object_addr =
1989 EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
1990 }
1991 break;
1992
1993 case kVirtual:
1994 DCHECK(vtable_idx != -1);
1995 callee_method_object_addr =
1996 EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
1997 break;
1998
1999 case kSuper:
2000 LOG(FATAL) << "invoke-super should be promoted to invoke-direct in "
2001 "the fast path.";
2002 break;
2003
2004 case kInterface:
2005 callee_method_object_addr =
2006 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx,
2007 invoke_type, this_addr,
2008 dex_pc, is_fast_path);
2009 break;
2010 }
2011 }
2012
2013 // Load the actual parameter
2014 std::vector<llvm::Value*> args;
2015
2016 args.push_back(callee_method_object_addr); // method object for callee
2017
2018 for (uint32_t i = 3; i < call_inst.getNumArgOperands(); ++i) {
2019 args.push_back(call_inst.getArgOperand(i));
2020 }
2021
2022 llvm::Value* code_addr;
2023 if (direct_code != 0u &&
2024 direct_code != static_cast<uintptr_t>(-1)) {
2025 code_addr =
2026 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_code),
2027 GetFunctionType(callee_method_idx, is_static)->getPointerTo());
2028 } else {
2029 code_addr =
2030 irb_.LoadFromObjectOffset(callee_method_object_addr,
2031 Method::GetCodeOffset().Int32Value(),
2032 GetFunctionType(callee_method_idx, is_static)->getPointerTo(),
2033 kTBAAJRuntime);
2034 }
2035
2036 // Invoke callee
2037 EmitUpdateDexPC(dex_pc);
2038 llvm::Value* retval = irb_.CreateCall(code_addr, args);
2039 EmitGuard_ExceptionLandingPad(dex_pc);
2040
2041 return retval;
2042}
2043
2044llvm::Value* GBCExpanderPass::Expand_OptArrayLength(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002045 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2046 // Get the array object address
2047 llvm::Value* array_addr = call_inst.getArgOperand(1);
2048
2049 // TODO: opt_flags
2050 EmitGuard_NullPointerException(dex_pc, array_addr);
2051
2052 // Get the array length and store it to the register
2053 return EmitLoadArrayLength(array_addr);
2054}
2055
2056llvm::Value* GBCExpanderPass::Expand_NewArray(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002057 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2058 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2059 llvm::Value* length = call_inst.getArgOperand(1);
2060
2061 return EmitAllocNewArray(dex_pc, length, type_idx, false);
2062}
2063
2064llvm::Value* GBCExpanderPass::Expand_HLFilledNewArray(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002065 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2066 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(1));
2067 uint32_t length = call_inst.getNumArgOperands() - 3;
2068
2069 llvm::Value* object_addr =
2070 EmitAllocNewArray(dex_pc, irb_.getInt32(length), type_idx, true);
2071
2072 if (length > 0) {
2073 // Check for the element type
2074 uint32_t type_desc_len = 0;
2075 const char* type_desc =
2076 dex_file_->StringByTypeIdx(type_idx, &type_desc_len);
2077
2078 DCHECK_GE(type_desc_len, 2u); // should be guaranteed by verifier
2079 DCHECK_EQ(type_desc[0], '['); // should be guaranteed by verifier
2080 bool is_elem_int_ty = (type_desc[1] == 'I');
2081
2082 uint32_t alignment;
2083 llvm::Constant* elem_size;
2084 llvm::PointerType* field_type;
2085
2086 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
2087 // as the element, thus we are only checking 2 cases: primitive int and
2088 // non-primitive type.
2089 if (is_elem_int_ty) {
2090 alignment = sizeof(int32_t);
2091 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
2092 field_type = irb_.getJIntTy()->getPointerTo();
2093 } else {
2094 alignment = irb_.getSizeOfPtrEquivInt();
2095 elem_size = irb_.getSizeOfPtrEquivIntValue();
2096 field_type = irb_.getJObjectTy()->getPointerTo();
2097 }
2098
2099 llvm::Value* data_field_offset =
2100 irb_.getPtrEquivInt(Array::DataOffset(alignment).Int32Value());
2101
2102 llvm::Value* data_field_addr =
2103 irb_.CreatePtrDisp(object_addr, data_field_offset, field_type);
2104
2105 // TODO: Tune this code. Currently we are generating one instruction for
2106 // one element which may be very space consuming. Maybe changing to use
2107 // memcpy may help; however, since we can't guarantee that the alloca of
2108 // dalvik register are continuous, we can't perform such optimization yet.
2109 for (uint32_t i = 0; i < length; ++i) {
2110 llvm::Value* reg_value = call_inst.getArgOperand(i+3);
2111
2112 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
2113
2114 data_field_addr =
2115 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
2116 }
2117 }
2118
2119 return object_addr;
2120}
2121
2122void GBCExpanderPass::Expand_HLFillArrayData(llvm::CallInst& call_inst) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002123 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2124 int32_t payload_offset = static_cast<int32_t>(dex_pc) +
2125 LV2SInt(call_inst.getArgOperand(0));
2126 llvm::Value* array_addr = call_inst.getArgOperand(1);
2127
2128 const Instruction::ArrayDataPayload* payload =
2129 reinterpret_cast<const Instruction::ArrayDataPayload*>(
2130 code_item_->insns_ + payload_offset);
2131
2132 if (payload->element_count == 0) {
2133 // When the number of the elements in the payload is zero, we don't have
2134 // to copy any numbers. However, we should check whether the array object
2135 // address is equal to null or not.
2136 EmitGuard_NullPointerException(dex_pc, array_addr);
2137 } else {
2138 // To save the code size, we are going to call the runtime function to
2139 // copy the content from DexFile.
2140
2141 // NOTE: We will check for the NullPointerException in the runtime.
2142
2143 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::FillArrayData);
2144
2145 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2146
2147 EmitUpdateDexPC(dex_pc);
2148
2149 irb_.CreateCall4(runtime_func,
2150 method_object_addr, irb_.getInt32(dex_pc),
2151 array_addr, irb_.getInt32(payload_offset));
2152
2153 EmitGuard_ExceptionLandingPad(dex_pc);
2154 }
2155
2156 return;
2157}
2158
2159llvm::Value* GBCExpanderPass::EmitAllocNewArray(uint32_t dex_pc,
2160 llvm::Value* array_length_value,
2161 uint32_t type_idx,
2162 bool is_filled_new_array) {
2163 llvm::Function* runtime_func;
2164
2165 bool skip_access_check =
2166 compiler_->CanAccessTypeWithoutChecks(method_idx_, dex_cache_,
2167 *dex_file_, type_idx);
2168
2169
2170 if (is_filled_new_array) {
2171 runtime_func = skip_access_check ?
2172 irb_.GetRuntime(runtime_support::CheckAndAllocArray) :
2173 irb_.GetRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck);
2174 } else {
2175 runtime_func = skip_access_check ?
2176 irb_.GetRuntime(runtime_support::AllocArray) :
2177 irb_.GetRuntime(runtime_support::AllocArrayWithAccessCheck);
2178 }
2179
2180 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2181
2182 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2183
2184 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2185
2186 EmitUpdateDexPC(dex_pc);
2187
2188 llvm::Value* object_addr =
2189 irb_.CreateCall4(runtime_func, type_index_value, method_object_addr,
2190 array_length_value, thread_object_addr);
2191
2192 EmitGuard_ExceptionLandingPad(dex_pc);
2193
2194 return object_addr;
2195}
2196
2197llvm::Value* GBCExpanderPass::
2198EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
2199 InvokeType invoke_type,
2200 llvm::Value* this_addr,
2201 uint32_t dex_pc,
2202 bool is_fast_path) {
2203
2204 llvm::Function* runtime_func = NULL;
2205
2206 switch (invoke_type) {
2207 case kStatic:
2208 runtime_func = irb_.GetRuntime(runtime_support::FindStaticMethodWithAccessCheck);
2209 break;
2210
2211 case kDirect:
2212 runtime_func = irb_.GetRuntime(runtime_support::FindDirectMethodWithAccessCheck);
2213 break;
2214
2215 case kVirtual:
2216 runtime_func = irb_.GetRuntime(runtime_support::FindVirtualMethodWithAccessCheck);
2217 break;
2218
2219 case kSuper:
2220 runtime_func = irb_.GetRuntime(runtime_support::FindSuperMethodWithAccessCheck);
2221 break;
2222
2223 case kInterface:
2224 if (is_fast_path) {
2225 runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethod);
2226 } else {
2227 runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethodWithAccessCheck);
2228 }
2229 break;
2230 }
2231
2232 llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
2233
2234 if (this_addr == NULL) {
2235 DCHECK_EQ(invoke_type, kStatic);
2236 this_addr = irb_.getJNull();
2237 }
2238
2239 llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
2240
2241 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2242
2243 EmitUpdateDexPC(dex_pc);
2244
2245 llvm::Value* callee_method_object_addr =
2246 irb_.CreateCall4(runtime_func,
2247 callee_method_idx_value,
2248 this_addr,
2249 caller_method_object_addr,
2250 thread_object_addr);
2251
2252 EmitGuard_ExceptionLandingPad(dex_pc);
2253
2254 return callee_method_object_addr;
2255}
2256
TDYa1275e869b62012-07-25 00:45:39 -07002257void GBCExpanderPass::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
2258 // Using runtime support, let the target can override by InlineAssembly.
2259 irb_.Runtime().EmitMarkGCCard(value, target_addr);
2260}
2261
2262void GBCExpanderPass::EmitUpdateDexPC(uint32_t dex_pc) {
2263 irb_.StoreToObjectOffset(shadow_frame_,
2264 ShadowFrame::DexPCOffset(),
2265 irb_.getInt32(dex_pc),
2266 kTBAAShadowFrame);
2267}
2268
2269void GBCExpanderPass::EmitGuard_DivZeroException(uint32_t dex_pc,
2270 llvm::Value* denominator,
2271 JType op_jty) {
2272 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
2273
2274 llvm::Constant* zero = irb_.getJZero(op_jty);
2275
2276 llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
2277
2278 llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
2279
2280 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
2281
2282 irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
2283
2284 irb_.SetInsertPoint(block_exception);
2285 EmitUpdateDexPC(dex_pc);
2286 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowDivZeroException));
2287 EmitBranchExceptionLandingPad(dex_pc);
2288
2289 irb_.SetInsertPoint(block_continue);
2290}
2291
2292void GBCExpanderPass::EmitGuard_NullPointerException(uint32_t dex_pc,
2293 llvm::Value* object) {
2294 llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
2295
2296 llvm::BasicBlock* block_exception =
2297 CreateBasicBlockWithDexPC(dex_pc, "nullp");
2298
2299 llvm::BasicBlock* block_continue =
2300 CreateBasicBlockWithDexPC(dex_pc, "cont");
2301
2302 irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
2303
2304 irb_.SetInsertPoint(block_exception);
2305 EmitUpdateDexPC(dex_pc);
2306 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowNullPointerException),
2307 irb_.getInt32(dex_pc));
2308 EmitBranchExceptionLandingPad(dex_pc);
2309
2310 irb_.SetInsertPoint(block_continue);
2311}
2312
2313void
2314GBCExpanderPass::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
2315 llvm::Value* array,
2316 llvm::Value* index) {
2317 llvm::Value* array_len = EmitLoadArrayLength(array);
2318
2319 llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
2320
2321 llvm::BasicBlock* block_exception =
2322 CreateBasicBlockWithDexPC(dex_pc, "overflow");
2323
2324 llvm::BasicBlock* block_continue =
2325 CreateBasicBlockWithDexPC(dex_pc, "cont");
2326
2327 irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
2328
2329 irb_.SetInsertPoint(block_exception);
2330
2331 EmitUpdateDexPC(dex_pc);
2332 irb_.CreateCall2(irb_.GetRuntime(runtime_support::ThrowIndexOutOfBounds), index, array_len);
2333 EmitBranchExceptionLandingPad(dex_pc);
2334
2335 irb_.SetInsertPoint(block_continue);
2336}
2337
2338void GBCExpanderPass::EmitGuard_ArrayException(uint32_t dex_pc,
2339 llvm::Value* array,
2340 llvm::Value* index) {
2341 EmitGuard_NullPointerException(dex_pc, array);
2342 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array, index);
2343}
2344
2345llvm::FunctionType* GBCExpanderPass::GetFunctionType(uint32_t method_idx,
2346 bool is_static) {
2347 // Get method signature
2348 DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
2349
2350 uint32_t shorty_size;
2351 const char* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
2352 CHECK_GE(shorty_size, 1u);
2353
2354 // Get return type
2355 llvm::Type* ret_type = irb_.getJType(shorty[0], kAccurate);
2356
2357 // Get argument type
2358 std::vector<llvm::Type*> args_type;
2359
2360 args_type.push_back(irb_.getJObjectTy()); // method object pointer
2361
2362 if (!is_static) {
2363 args_type.push_back(irb_.getJType('L', kAccurate)); // "this" object pointer
2364 }
2365
2366 for (uint32_t i = 1; i < shorty_size; ++i) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002367#if defined(ART_USE_QUICK_COMPILER)
2368 char shorty_type = shorty[i];
2369 switch(shorty_type) {
2370 case 'Z' : shorty_type = 'I'; break;
2371 case 'B' : shorty_type = 'I'; break;
2372 case 'S' : shorty_type = 'I'; break;
2373 case 'C' : shorty_type = 'I'; break;
2374 default: break;
2375 }
2376 args_type.push_back(irb_.getJType(shorty_type, kAccurate));
2377#else
TDYa1275e869b62012-07-25 00:45:39 -07002378 args_type.push_back(irb_.getJType(shorty[i], kAccurate));
TDYa127f71bf5a2012-07-29 20:09:52 -07002379#endif
TDYa1275e869b62012-07-25 00:45:39 -07002380 }
2381
2382 return llvm::FunctionType::get(ret_type, args_type, false);
2383}
2384
2385
2386llvm::BasicBlock* GBCExpanderPass::
2387CreateBasicBlockWithDexPC(uint32_t dex_pc, const char* postfix) {
2388 std::string name;
2389
2390#if !defined(NDEBUG)
2391 StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
2392#endif
2393
2394 return llvm::BasicBlock::Create(context_, name, func_);
2395}
2396
2397llvm::BasicBlock* GBCExpanderPass::GetBasicBlock(uint32_t dex_pc) {
2398 DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
2399
2400 return basic_blocks_[dex_pc];
2401}
2402
2403int32_t GBCExpanderPass::GetTryItemOffset(uint32_t dex_pc) {
2404 int32_t min = 0;
2405 int32_t max = code_item_->tries_size_ - 1;
2406
2407 while (min <= max) {
2408 int32_t mid = min + (max - min) / 2;
2409
2410 const DexFile::TryItem* ti = DexFile::GetTryItems(*code_item_, mid);
2411 uint32_t start = ti->start_addr_;
2412 uint32_t end = start + ti->insn_count_;
2413
2414 if (dex_pc < start) {
2415 max = mid - 1;
2416 } else if (dex_pc >= end) {
2417 min = mid + 1;
2418 } else {
2419 return mid; // found
2420 }
2421 }
2422
2423 return -1; // not found
2424}
2425
2426llvm::BasicBlock* GBCExpanderPass::GetLandingPadBasicBlock(uint32_t dex_pc) {
2427 // Find the try item for this address in this method
2428 int32_t ti_offset = GetTryItemOffset(dex_pc);
2429
2430 if (ti_offset == -1) {
2431 return NULL; // No landing pad is available for this address.
2432 }
2433
2434 // Check for the existing landing pad basic block
2435 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2436 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
2437
2438 if (block_lpad) {
2439 // We have generated landing pad for this try item already. Return the
2440 // same basic block.
2441 return block_lpad;
2442 }
2443
2444 // Get try item from code item
2445 const DexFile::TryItem* ti = DexFile::GetTryItems(*code_item_, ti_offset);
2446
2447 std::string lpadname;
2448
2449#if !defined(NDEBUG)
2450 StringAppendF(&lpadname, "lpad%d_%04x_to_%04x", ti_offset, ti->start_addr_, ti->handler_off_);
2451#endif
2452
2453 // Create landing pad basic block
2454 block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
2455
2456 // Change IRBuilder insert point
2457 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2458 irb_.SetInsertPoint(block_lpad);
2459
2460 // Find catch block with matching type
2461 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2462
2463 llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
2464
2465 llvm::Value* catch_handler_index_value =
2466 irb_.CreateCall2(irb_.GetRuntime(runtime_support::FindCatchBlock),
2467 method_object_addr, ti_offset_value);
2468
2469 // Switch instruction (Go to unwind basic block by default)
2470 llvm::SwitchInst* sw =
2471 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
2472
2473 // Cases with matched catch block
2474 CatchHandlerIterator iter(*code_item_, ti->start_addr_);
2475
2476 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
2477 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
2478 }
2479
2480 // Restore the orignal insert point for IRBuilder
2481 irb_.restoreIP(irb_ip_original);
2482
2483 // Cache this landing pad
2484 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2485 basic_block_landing_pads_[ti_offset] = block_lpad;
2486
2487 return block_lpad;
2488}
2489
2490llvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() {
2491 // Check the existing unwinding baisc block block
2492 if (basic_block_unwind_ != NULL) {
2493 return basic_block_unwind_;
2494 }
2495
2496 // Create new basic block for unwinding
2497 basic_block_unwind_ =
2498 llvm::BasicBlock::Create(context_, "exception_unwind", func_);
2499
2500 // Change IRBuilder insert point
2501 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2502 irb_.SetInsertPoint(basic_block_unwind_);
2503
2504 // Pop the shadow frame
2505 Expand_PopShadowFrame();
2506
2507 // Emit the code to return default value (zero) for the given return type.
2508 char ret_shorty = oat_compilation_unit_->GetShorty()[0];
2509 if (ret_shorty == 'V') {
2510 irb_.CreateRetVoid();
2511 } else {
2512 irb_.CreateRet(irb_.getJZero(ret_shorty));
2513 }
2514
2515 // Restore the orignal insert point for IRBuilder
2516 irb_.restoreIP(irb_ip_original);
2517
2518 return basic_block_unwind_;
2519}
2520
2521void GBCExpanderPass::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
2522 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
2523 irb_.CreateBr(lpad);
2524 } else {
2525 irb_.CreateBr(GetUnwindBasicBlock());
2526 }
2527}
2528
2529void GBCExpanderPass::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
2530 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
2531
2532 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
2533
2534 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
2535 irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
2536 } else {
2537 irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
2538 }
2539
2540 irb_.SetInsertPoint(block_cont);
2541}
2542
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002543llvm::Value*
2544GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
2545 llvm::CallInst& call_inst) {
2546 switch (intr_id) {
2547 //==- Thread -----------------------------------------------------------==//
2548 case IntrinsicHelper::GetCurrentThread: {
TDYa127b672d1e2012-06-28 21:21:45 -07002549 return irb_.Runtime().EmitGetCurrentThread();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002550 }
Logan Chiend54a23d2012-07-24 11:19:23 -07002551 case IntrinsicHelper::TestSuspend:
Logan Chien75e4b602012-07-23 14:24:12 -07002552 case IntrinsicHelper::CheckSuspend: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002553 Expand_TestSuspend(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002554 return NULL;
2555 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002556 case IntrinsicHelper::MarkGCCard: {
TDYa1279a129452012-07-19 03:10:08 -07002557 Expand_MarkGCCard(call_inst);
2558 return NULL;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002559 }
Logan Chien75e4b602012-07-23 14:24:12 -07002560
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002561 //==- Exception --------------------------------------------------------==//
2562 case IntrinsicHelper::ThrowException: {
2563 return ExpandToRuntime(runtime_support::ThrowException, call_inst);
2564 }
TDYa127f71bf5a2012-07-29 20:09:52 -07002565 case IntrinsicHelper::HLThrowException: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002566 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2567
2568 EmitUpdateDexPC(dex_pc);
2569
2570 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowException),
2571 call_inst.getArgOperand(0));
2572
2573 EmitGuard_ExceptionLandingPad(dex_pc);
2574 return NULL;
2575 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002576 case IntrinsicHelper::GetException: {
2577 return Expand_GetException();
2578 }
2579 case IntrinsicHelper::IsExceptionPending: {
2580 return irb_.Runtime().EmitIsExceptionPending();
2581 }
2582 case IntrinsicHelper::FindCatchBlock: {
2583 return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
2584 }
2585 case IntrinsicHelper::ThrowDivZeroException: {
2586 return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
2587 }
2588 case IntrinsicHelper::ThrowNullPointerException: {
2589 return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
2590 }
2591 case IntrinsicHelper::ThrowIndexOutOfBounds: {
2592 return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
2593 }
Logan Chien75e4b602012-07-23 14:24:12 -07002594
2595 //==- Const String -----------------------------------------------------==//
2596 case IntrinsicHelper::ConstString: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002597 return Expand_ConstString(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002598 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002599 case IntrinsicHelper::LoadStringFromDexCache: {
2600 return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
2601 }
2602 case IntrinsicHelper::ResolveString: {
2603 return ExpandToRuntime(runtime_support::ResolveString, call_inst);
2604 }
Logan Chien75e4b602012-07-23 14:24:12 -07002605
2606 //==- Const Class ------------------------------------------------------==//
2607 case IntrinsicHelper::ConstClass: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002608 return Expand_ConstClass(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002609 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002610 case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
2611 return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
2612 }
2613 case IntrinsicHelper::LoadTypeFromDexCache: {
2614 return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
2615 }
2616 case IntrinsicHelper::InitializeType: {
2617 return ExpandToRuntime(runtime_support::InitializeType, call_inst);
2618 }
Logan Chien75e4b602012-07-23 14:24:12 -07002619
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002620 //==- Lock -------------------------------------------------------------==//
2621 case IntrinsicHelper::LockObject: {
2622 Expand_LockObject(call_inst.getArgOperand(0));
2623 return NULL;
2624 }
2625 case IntrinsicHelper::UnlockObject: {
2626 Expand_UnlockObject(call_inst.getArgOperand(0));
2627 return NULL;
2628 }
Logan Chien75e4b602012-07-23 14:24:12 -07002629
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002630 //==- Cast -------------------------------------------------------------==//
2631 case IntrinsicHelper::CheckCast: {
2632 return ExpandToRuntime(runtime_support::CheckCast, call_inst);
2633 }
Logan Chien75e4b602012-07-23 14:24:12 -07002634 case IntrinsicHelper::HLCheckCast: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002635 Expand_HLCheckCast(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002636 return NULL;
2637 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002638 case IntrinsicHelper::IsAssignable: {
2639 return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
2640 }
Logan Chien75e4b602012-07-23 14:24:12 -07002641
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002642 //==- Alloc ------------------------------------------------------------==//
2643 case IntrinsicHelper::AllocObject: {
2644 return ExpandToRuntime(runtime_support::AllocObject, call_inst);
2645 }
2646 case IntrinsicHelper::AllocObjectWithAccessCheck: {
2647 return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
2648 }
Logan Chien75e4b602012-07-23 14:24:12 -07002649
2650 //==- Instance ---------------------------------------------------------==//
2651 case IntrinsicHelper::NewInstance: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002652 return Expand_NewInstance(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002653 }
2654 case IntrinsicHelper::InstanceOf: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002655 return Expand_InstanceOf(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002656 }
2657
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002658 //==- Array ------------------------------------------------------------==//
Logan Chien75e4b602012-07-23 14:24:12 -07002659 case IntrinsicHelper::NewArray: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002660 return Expand_NewArray(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002661 }
2662 case IntrinsicHelper::OptArrayLength: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002663 return Expand_OptArrayLength(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002664 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002665 case IntrinsicHelper::ArrayLength: {
2666 return EmitLoadArrayLength(call_inst.getArgOperand(0));
2667 }
2668 case IntrinsicHelper::AllocArray: {
2669 return ExpandToRuntime(runtime_support::AllocArray, call_inst);
2670 }
2671 case IntrinsicHelper::AllocArrayWithAccessCheck: {
2672 return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
2673 call_inst);
2674 }
2675 case IntrinsicHelper::CheckAndAllocArray: {
2676 return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
2677 }
2678 case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
2679 return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
2680 call_inst);
2681 }
2682 case IntrinsicHelper::ArrayGet: {
2683 return Expand_ArrayGet(call_inst.getArgOperand(0),
2684 call_inst.getArgOperand(1),
2685 kInt);
2686 }
2687 case IntrinsicHelper::ArrayGetWide: {
2688 return Expand_ArrayGet(call_inst.getArgOperand(0),
2689 call_inst.getArgOperand(1),
2690 kLong);
2691 }
2692 case IntrinsicHelper::ArrayGetObject: {
2693 return Expand_ArrayGet(call_inst.getArgOperand(0),
2694 call_inst.getArgOperand(1),
2695 kObject);
2696 }
2697 case IntrinsicHelper::ArrayGetBoolean: {
2698 return Expand_ArrayGet(call_inst.getArgOperand(0),
2699 call_inst.getArgOperand(1),
2700 kBoolean);
2701 }
2702 case IntrinsicHelper::ArrayGetByte: {
2703 return Expand_ArrayGet(call_inst.getArgOperand(0),
2704 call_inst.getArgOperand(1),
2705 kByte);
2706 }
2707 case IntrinsicHelper::ArrayGetChar: {
2708 return Expand_ArrayGet(call_inst.getArgOperand(0),
2709 call_inst.getArgOperand(1),
2710 kChar);
2711 }
2712 case IntrinsicHelper::ArrayGetShort: {
2713 return Expand_ArrayGet(call_inst.getArgOperand(0),
2714 call_inst.getArgOperand(1),
2715 kShort);
2716 }
2717 case IntrinsicHelper::ArrayPut: {
2718 Expand_ArrayPut(call_inst.getArgOperand(0),
2719 call_inst.getArgOperand(1),
2720 call_inst.getArgOperand(2),
2721 kInt);
2722 return NULL;
2723 }
2724 case IntrinsicHelper::ArrayPutWide: {
2725 Expand_ArrayPut(call_inst.getArgOperand(0),
2726 call_inst.getArgOperand(1),
2727 call_inst.getArgOperand(2),
2728 kLong);
2729 return NULL;
2730 }
2731 case IntrinsicHelper::ArrayPutObject: {
2732 Expand_ArrayPut(call_inst.getArgOperand(0),
2733 call_inst.getArgOperand(1),
2734 call_inst.getArgOperand(2),
2735 kObject);
2736 return NULL;
2737 }
2738 case IntrinsicHelper::ArrayPutBoolean: {
2739 Expand_ArrayPut(call_inst.getArgOperand(0),
2740 call_inst.getArgOperand(1),
2741 call_inst.getArgOperand(2),
2742 kBoolean);
2743 return NULL;
2744 }
2745 case IntrinsicHelper::ArrayPutByte: {
2746 Expand_ArrayPut(call_inst.getArgOperand(0),
2747 call_inst.getArgOperand(1),
2748 call_inst.getArgOperand(2),
2749 kByte);
2750 return NULL;
2751 }
2752 case IntrinsicHelper::ArrayPutChar: {
2753 Expand_ArrayPut(call_inst.getArgOperand(0),
2754 call_inst.getArgOperand(1),
2755 call_inst.getArgOperand(2),
2756 kChar);
2757 return NULL;
2758 }
2759 case IntrinsicHelper::ArrayPutShort: {
2760 Expand_ArrayPut(call_inst.getArgOperand(0),
2761 call_inst.getArgOperand(1),
2762 call_inst.getArgOperand(2),
2763 kShort);
2764 return NULL;
2765 }
2766 case IntrinsicHelper::CheckPutArrayElement: {
2767 return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
2768 }
2769 case IntrinsicHelper::FilledNewArray: {
2770 Expand_FilledNewArray(call_inst);
2771 return NULL;
2772 }
2773 case IntrinsicHelper::FillArrayData: {
2774 return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
2775 }
Logan Chien75e4b602012-07-23 14:24:12 -07002776 case IntrinsicHelper::HLFillArrayData: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002777 Expand_HLFillArrayData(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002778 return NULL;
2779 }
2780 case IntrinsicHelper::HLFilledNewArray: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002781 return Expand_HLFilledNewArray(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002782 }
2783
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002784 //==- Instance Field ---------------------------------------------------==//
2785 case IntrinsicHelper::InstanceFieldGet:
2786 case IntrinsicHelper::InstanceFieldGetBoolean:
2787 case IntrinsicHelper::InstanceFieldGetByte:
2788 case IntrinsicHelper::InstanceFieldGetChar:
2789 case IntrinsicHelper::InstanceFieldGetShort: {
2790 return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
2791 }
2792 case IntrinsicHelper::InstanceFieldGetWide: {
2793 return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
2794 }
2795 case IntrinsicHelper::InstanceFieldGetObject: {
2796 return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
2797 }
2798 case IntrinsicHelper::InstanceFieldGetFast: {
2799 return Expand_IGetFast(call_inst.getArgOperand(0),
2800 call_inst.getArgOperand(1),
2801 call_inst.getArgOperand(2),
2802 kInt);
2803 }
2804 case IntrinsicHelper::InstanceFieldGetWideFast: {
2805 return Expand_IGetFast(call_inst.getArgOperand(0),
2806 call_inst.getArgOperand(1),
2807 call_inst.getArgOperand(2),
2808 kLong);
2809 }
2810 case IntrinsicHelper::InstanceFieldGetObjectFast: {
2811 return Expand_IGetFast(call_inst.getArgOperand(0),
2812 call_inst.getArgOperand(1),
2813 call_inst.getArgOperand(2),
2814 kObject);
2815 }
2816 case IntrinsicHelper::InstanceFieldGetBooleanFast: {
2817 return Expand_IGetFast(call_inst.getArgOperand(0),
2818 call_inst.getArgOperand(1),
2819 call_inst.getArgOperand(2),
2820 kBoolean);
2821 }
2822 case IntrinsicHelper::InstanceFieldGetByteFast: {
2823 return Expand_IGetFast(call_inst.getArgOperand(0),
2824 call_inst.getArgOperand(1),
2825 call_inst.getArgOperand(2),
2826 kByte);
2827 }
2828 case IntrinsicHelper::InstanceFieldGetCharFast: {
2829 return Expand_IGetFast(call_inst.getArgOperand(0),
2830 call_inst.getArgOperand(1),
2831 call_inst.getArgOperand(2),
2832 kChar);
2833 }
2834 case IntrinsicHelper::InstanceFieldGetShortFast: {
2835 return Expand_IGetFast(call_inst.getArgOperand(0),
2836 call_inst.getArgOperand(1),
2837 call_inst.getArgOperand(2),
2838 kShort);
2839 }
2840 case IntrinsicHelper::InstanceFieldPut:
2841 case IntrinsicHelper::InstanceFieldPutBoolean:
2842 case IntrinsicHelper::InstanceFieldPutByte:
2843 case IntrinsicHelper::InstanceFieldPutChar:
2844 case IntrinsicHelper::InstanceFieldPutShort: {
2845 return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
2846 }
2847 case IntrinsicHelper::InstanceFieldPutWide: {
2848 return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
2849 }
2850 case IntrinsicHelper::InstanceFieldPutObject: {
2851 return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
2852 }
2853 case IntrinsicHelper::InstanceFieldPutFast: {
2854 Expand_IPutFast(call_inst.getArgOperand(0),
2855 call_inst.getArgOperand(1),
2856 call_inst.getArgOperand(2),
2857 call_inst.getArgOperand(3),
2858 kInt);
2859 return NULL;
2860 }
2861 case IntrinsicHelper::InstanceFieldPutWideFast: {
2862 Expand_IPutFast(call_inst.getArgOperand(0),
2863 call_inst.getArgOperand(1),
2864 call_inst.getArgOperand(2),
2865 call_inst.getArgOperand(3),
2866 kLong);
2867 return NULL;
2868 }
2869 case IntrinsicHelper::InstanceFieldPutObjectFast: {
2870 Expand_IPutFast(call_inst.getArgOperand(0),
2871 call_inst.getArgOperand(1),
2872 call_inst.getArgOperand(2),
2873 call_inst.getArgOperand(3),
2874 kObject);
2875 return NULL;
2876 }
2877 case IntrinsicHelper::InstanceFieldPutBooleanFast: {
2878 Expand_IPutFast(call_inst.getArgOperand(0),
2879 call_inst.getArgOperand(1),
2880 call_inst.getArgOperand(2),
2881 call_inst.getArgOperand(3),
2882 kBoolean);
2883 return NULL;
2884 }
2885 case IntrinsicHelper::InstanceFieldPutByteFast: {
2886 Expand_IPutFast(call_inst.getArgOperand(0),
2887 call_inst.getArgOperand(1),
2888 call_inst.getArgOperand(2),
2889 call_inst.getArgOperand(3),
2890 kByte);
2891 return NULL;
2892 }
2893 case IntrinsicHelper::InstanceFieldPutCharFast: {
2894 Expand_IPutFast(call_inst.getArgOperand(0),
2895 call_inst.getArgOperand(1),
2896 call_inst.getArgOperand(2),
2897 call_inst.getArgOperand(3),
2898 kChar);
2899 return NULL;
2900 }
2901 case IntrinsicHelper::InstanceFieldPutShortFast: {
2902 Expand_IPutFast(call_inst.getArgOperand(0),
2903 call_inst.getArgOperand(1),
2904 call_inst.getArgOperand(2),
2905 call_inst.getArgOperand(3),
2906 kShort);
2907 return NULL;
2908 }
Logan Chien75e4b602012-07-23 14:24:12 -07002909
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002910 //==- Static Field -----------------------------------------------------==//
2911 case IntrinsicHelper::StaticFieldGet:
2912 case IntrinsicHelper::StaticFieldGetBoolean:
2913 case IntrinsicHelper::StaticFieldGetByte:
2914 case IntrinsicHelper::StaticFieldGetChar:
2915 case IntrinsicHelper::StaticFieldGetShort: {
2916 return ExpandToRuntime(runtime_support::Get32Static, call_inst);
2917 }
2918 case IntrinsicHelper::StaticFieldGetWide: {
2919 return ExpandToRuntime(runtime_support::Get64Static, call_inst);
2920 }
2921 case IntrinsicHelper::StaticFieldGetObject: {
2922 return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
2923 }
2924 case IntrinsicHelper::StaticFieldGetFast: {
2925 return Expand_SGetFast(call_inst.getArgOperand(0),
2926 call_inst.getArgOperand(1),
2927 call_inst.getArgOperand(2),
2928 kInt);
2929 }
2930 case IntrinsicHelper::StaticFieldGetWideFast: {
2931 return Expand_SGetFast(call_inst.getArgOperand(0),
2932 call_inst.getArgOperand(1),
2933 call_inst.getArgOperand(2),
2934 kLong);
2935 }
2936 case IntrinsicHelper::StaticFieldGetObjectFast: {
2937 return Expand_SGetFast(call_inst.getArgOperand(0),
2938 call_inst.getArgOperand(1),
2939 call_inst.getArgOperand(2),
2940 kObject);
2941 }
2942 case IntrinsicHelper::StaticFieldGetBooleanFast: {
2943 return Expand_SGetFast(call_inst.getArgOperand(0),
2944 call_inst.getArgOperand(1),
2945 call_inst.getArgOperand(2),
2946 kBoolean);
2947 }
2948 case IntrinsicHelper::StaticFieldGetByteFast: {
2949 return Expand_SGetFast(call_inst.getArgOperand(0),
2950 call_inst.getArgOperand(1),
2951 call_inst.getArgOperand(2),
2952 kByte);
2953 }
2954 case IntrinsicHelper::StaticFieldGetCharFast: {
2955 return Expand_SGetFast(call_inst.getArgOperand(0),
2956 call_inst.getArgOperand(1),
2957 call_inst.getArgOperand(2),
2958 kChar);
2959 }
2960 case IntrinsicHelper::StaticFieldGetShortFast: {
2961 return Expand_SGetFast(call_inst.getArgOperand(0),
2962 call_inst.getArgOperand(1),
2963 call_inst.getArgOperand(2),
2964 kShort);
2965 }
2966 case IntrinsicHelper::StaticFieldPut:
2967 case IntrinsicHelper::StaticFieldPutBoolean:
2968 case IntrinsicHelper::StaticFieldPutByte:
2969 case IntrinsicHelper::StaticFieldPutChar:
2970 case IntrinsicHelper::StaticFieldPutShort: {
2971 return ExpandToRuntime(runtime_support::Set32Static, call_inst);
2972 }
2973 case IntrinsicHelper::StaticFieldPutWide: {
2974 return ExpandToRuntime(runtime_support::Set64Static, call_inst);
2975 }
2976 case IntrinsicHelper::StaticFieldPutObject: {
2977 return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
2978 }
2979 case IntrinsicHelper::StaticFieldPutFast: {
2980 Expand_SPutFast(call_inst.getArgOperand(0),
2981 call_inst.getArgOperand(1),
2982 call_inst.getArgOperand(2),
2983 call_inst.getArgOperand(3),
2984 kInt);
2985 return NULL;
2986 }
2987 case IntrinsicHelper::StaticFieldPutWideFast: {
2988 Expand_SPutFast(call_inst.getArgOperand(0),
2989 call_inst.getArgOperand(1),
2990 call_inst.getArgOperand(2),
2991 call_inst.getArgOperand(3),
2992 kLong);
2993 return NULL;
2994 }
2995 case IntrinsicHelper::StaticFieldPutObjectFast: {
2996 Expand_SPutFast(call_inst.getArgOperand(0),
2997 call_inst.getArgOperand(1),
2998 call_inst.getArgOperand(2),
2999 call_inst.getArgOperand(3),
3000 kObject);
3001 return NULL;
3002 }
3003 case IntrinsicHelper::StaticFieldPutBooleanFast: {
3004 Expand_SPutFast(call_inst.getArgOperand(0),
3005 call_inst.getArgOperand(1),
3006 call_inst.getArgOperand(2),
3007 call_inst.getArgOperand(3),
3008 kBoolean);
3009 return NULL;
3010 }
3011 case IntrinsicHelper::StaticFieldPutByteFast: {
3012 Expand_SPutFast(call_inst.getArgOperand(0),
3013 call_inst.getArgOperand(1),
3014 call_inst.getArgOperand(2),
3015 call_inst.getArgOperand(3),
3016 kByte);
3017 return NULL;
3018 }
3019 case IntrinsicHelper::StaticFieldPutCharFast: {
3020 Expand_SPutFast(call_inst.getArgOperand(0),
3021 call_inst.getArgOperand(1),
3022 call_inst.getArgOperand(2),
3023 call_inst.getArgOperand(3),
3024 kChar);
3025 return NULL;
3026 }
3027 case IntrinsicHelper::StaticFieldPutShortFast: {
3028 Expand_SPutFast(call_inst.getArgOperand(0),
3029 call_inst.getArgOperand(1),
3030 call_inst.getArgOperand(2),
3031 call_inst.getArgOperand(3),
3032 kShort);
3033 return NULL;
3034 }
3035 case IntrinsicHelper::LoadDeclaringClassSSB: {
3036 return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
3037 }
3038 case IntrinsicHelper::LoadClassSSBFromDexCache: {
3039 return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
3040 }
3041 case IntrinsicHelper::InitializeAndLoadClassSSB: {
3042 return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
3043 }
Logan Chien75e4b602012-07-23 14:24:12 -07003044
3045 //==- High-level Array -------------------------------------------------==//
3046 case IntrinsicHelper::HLArrayGet: {
TDYa1275a26d442012-07-26 18:58:38 -07003047 return Expand_HLArrayGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003048 }
3049 case IntrinsicHelper::HLArrayGetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003050 return Expand_HLArrayGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003051 }
3052 case IntrinsicHelper::HLArrayGetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003053 return Expand_HLArrayGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003054 }
3055 case IntrinsicHelper::HLArrayGetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003056 return Expand_HLArrayGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003057 }
3058 case IntrinsicHelper::HLArrayGetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003059 return Expand_HLArrayGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003060 }
3061 case IntrinsicHelper::HLArrayGetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003062 return Expand_HLArrayGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003063 }
3064 case IntrinsicHelper::HLArrayGetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003065 return Expand_HLArrayGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003066 }
3067 case IntrinsicHelper::HLArrayGetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003068 return Expand_HLArrayGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003069 }
3070 case IntrinsicHelper::HLArrayGetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003071 return Expand_HLArrayGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003072 }
3073 case IntrinsicHelper::HLArrayPut: {
TDYa1275a26d442012-07-26 18:58:38 -07003074 Expand_HLArrayPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003075 return NULL;
3076 }
3077 case IntrinsicHelper::HLArrayPutBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003078 Expand_HLArrayPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003079 return NULL;
3080 }
3081 case IntrinsicHelper::HLArrayPutByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003082 Expand_HLArrayPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003083 return NULL;
3084 }
3085 case IntrinsicHelper::HLArrayPutChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003086 Expand_HLArrayPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003087 return NULL;
3088 }
3089 case IntrinsicHelper::HLArrayPutShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003090 Expand_HLArrayPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003091 return NULL;
3092 }
3093 case IntrinsicHelper::HLArrayPutFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003094 Expand_HLArrayPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003095 return NULL;
3096 }
3097 case IntrinsicHelper::HLArrayPutWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003098 Expand_HLArrayPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003099 return NULL;
3100 }
3101 case IntrinsicHelper::HLArrayPutDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003102 Expand_HLArrayPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003103 return NULL;
3104 }
3105 case IntrinsicHelper::HLArrayPutObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003106 Expand_HLArrayPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003107 return NULL;
3108 }
3109
3110 //==- High-level Instance ----------------------------------------------==//
3111 case IntrinsicHelper::HLIGet: {
TDYa1275e869b62012-07-25 00:45:39 -07003112 return Expand_HLIGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003113 }
3114 case IntrinsicHelper::HLIGetBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07003115 return Expand_HLIGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003116 }
3117 case IntrinsicHelper::HLIGetByte: {
TDYa1275e869b62012-07-25 00:45:39 -07003118 return Expand_HLIGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003119 }
3120 case IntrinsicHelper::HLIGetChar: {
TDYa1275e869b62012-07-25 00:45:39 -07003121 return Expand_HLIGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003122 }
3123 case IntrinsicHelper::HLIGetShort: {
TDYa1275e869b62012-07-25 00:45:39 -07003124 return Expand_HLIGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003125 }
3126 case IntrinsicHelper::HLIGetFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07003127 return Expand_HLIGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003128 }
3129 case IntrinsicHelper::HLIGetWide: {
TDYa1275e869b62012-07-25 00:45:39 -07003130 return Expand_HLIGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003131 }
3132 case IntrinsicHelper::HLIGetDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07003133 return Expand_HLIGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003134 }
3135 case IntrinsicHelper::HLIGetObject: {
TDYa1275e869b62012-07-25 00:45:39 -07003136 return Expand_HLIGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003137 }
3138 case IntrinsicHelper::HLIPut: {
TDYa1275e869b62012-07-25 00:45:39 -07003139 Expand_HLIPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003140 return NULL;
3141 }
3142 case IntrinsicHelper::HLIPutBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07003143 Expand_HLIPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003144 return NULL;
3145 }
3146 case IntrinsicHelper::HLIPutByte: {
TDYa1275e869b62012-07-25 00:45:39 -07003147 Expand_HLIPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003148 return NULL;
3149 }
3150 case IntrinsicHelper::HLIPutChar: {
TDYa1275e869b62012-07-25 00:45:39 -07003151 Expand_HLIPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003152 return NULL;
3153 }
3154 case IntrinsicHelper::HLIPutShort: {
TDYa1275e869b62012-07-25 00:45:39 -07003155 Expand_HLIPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003156 return NULL;
3157 }
3158 case IntrinsicHelper::HLIPutFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07003159 Expand_HLIPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003160 return NULL;
3161 }
3162 case IntrinsicHelper::HLIPutWide: {
TDYa1275e869b62012-07-25 00:45:39 -07003163 Expand_HLIPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003164 return NULL;
3165 }
3166 case IntrinsicHelper::HLIPutDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07003167 Expand_HLIPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003168 return NULL;
3169 }
3170 case IntrinsicHelper::HLIPutObject: {
TDYa1275e869b62012-07-25 00:45:39 -07003171 Expand_HLIPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003172 return NULL;
3173 }
3174
3175 //==- High-level Invoke ------------------------------------------------==//
TDYa127f71bf5a2012-07-29 20:09:52 -07003176 case IntrinsicHelper::HLInvokeVoid:
3177 case IntrinsicHelper::HLInvokeObj:
3178 case IntrinsicHelper::HLInvokeInt:
3179 case IntrinsicHelper::HLInvokeFloat:
3180 case IntrinsicHelper::HLInvokeLong:
Logan Chien75e4b602012-07-23 14:24:12 -07003181 case IntrinsicHelper::HLInvokeDouble: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003182 return Expand_HLInvoke(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003183 }
3184
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003185 //==- Invoke -----------------------------------------------------------==//
3186 case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
3187 return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
3188 }
3189 case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
3190 return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
3191 }
3192 case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
3193 return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
3194 }
3195 case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
3196 return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
3197 }
3198 case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
3199 return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
3200 }
3201 case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
3202 return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
3203 }
3204 case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
3205 return Expand_GetVirtualCalleeMethodObjAddrFast(
3206 call_inst.getArgOperand(0), call_inst.getArgOperand(1));
3207 }
3208 case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
3209 return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
3210 }
3211 case IntrinsicHelper::InvokeRetVoid:
3212 case IntrinsicHelper::InvokeRetBoolean:
3213 case IntrinsicHelper::InvokeRetByte:
3214 case IntrinsicHelper::InvokeRetChar:
3215 case IntrinsicHelper::InvokeRetShort:
3216 case IntrinsicHelper::InvokeRetInt:
3217 case IntrinsicHelper::InvokeRetLong:
3218 case IntrinsicHelper::InvokeRetFloat:
3219 case IntrinsicHelper::InvokeRetDouble:
3220 case IntrinsicHelper::InvokeRetObject: {
3221 return Expand_Invoke(call_inst);
3222 }
Logan Chien75e4b602012-07-23 14:24:12 -07003223
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003224 //==- Math -------------------------------------------------------------==//
3225 case IntrinsicHelper::DivInt: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003226 return Expand_DivRem(call_inst, /* is_div */true, kInt);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003227 }
3228 case IntrinsicHelper::RemInt: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003229 return Expand_DivRem(call_inst, /* is_div */false, kInt);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003230 }
3231 case IntrinsicHelper::DivLong: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003232 return Expand_DivRem(call_inst, /* is_div */true, kLong);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003233 }
3234 case IntrinsicHelper::RemLong: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003235 return Expand_DivRem(call_inst, /* is_div */false, kLong);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003236 }
3237 case IntrinsicHelper::D2L: {
3238 return ExpandToRuntime(runtime_support::art_d2l, call_inst);
3239 }
3240 case IntrinsicHelper::D2I: {
3241 return ExpandToRuntime(runtime_support::art_d2i, call_inst);
3242 }
3243 case IntrinsicHelper::F2L: {
3244 return ExpandToRuntime(runtime_support::art_f2l, call_inst);
3245 }
3246 case IntrinsicHelper::F2I: {
3247 return ExpandToRuntime(runtime_support::art_f2i, call_inst);
3248 }
Logan Chien75e4b602012-07-23 14:24:12 -07003249
3250 //==- High-level Static ------------------------------------------------==//
3251 case IntrinsicHelper::HLSget: {
TDYa1275a26d442012-07-26 18:58:38 -07003252 return Expand_HLSget(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003253 }
3254 case IntrinsicHelper::HLSgetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003255 return Expand_HLSget(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003256 }
3257 case IntrinsicHelper::HLSgetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003258 return Expand_HLSget(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003259 }
3260 case IntrinsicHelper::HLSgetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003261 return Expand_HLSget(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003262 }
3263 case IntrinsicHelper::HLSgetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003264 return Expand_HLSget(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003265 }
3266 case IntrinsicHelper::HLSgetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003267 return Expand_HLSget(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003268 }
3269 case IntrinsicHelper::HLSgetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003270 return Expand_HLSget(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003271 }
3272 case IntrinsicHelper::HLSgetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003273 return Expand_HLSget(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003274 }
3275 case IntrinsicHelper::HLSgetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003276 return Expand_HLSget(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003277 }
3278 case IntrinsicHelper::HLSput: {
TDYa1275a26d442012-07-26 18:58:38 -07003279 Expand_HLSput(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003280 return NULL;
3281 }
3282 case IntrinsicHelper::HLSputBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003283 Expand_HLSput(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003284 return NULL;
3285 }
3286 case IntrinsicHelper::HLSputByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003287 Expand_HLSput(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003288 return NULL;
3289 }
3290 case IntrinsicHelper::HLSputChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003291 Expand_HLSput(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003292 return NULL;
3293 }
3294 case IntrinsicHelper::HLSputShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003295 Expand_HLSput(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003296 return NULL;
3297 }
3298 case IntrinsicHelper::HLSputFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003299 Expand_HLSput(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003300 return NULL;
3301 }
3302 case IntrinsicHelper::HLSputWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003303 Expand_HLSput(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003304 return NULL;
3305 }
3306 case IntrinsicHelper::HLSputDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003307 Expand_HLSput(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003308 return NULL;
3309 }
3310 case IntrinsicHelper::HLSputObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003311 Expand_HLSput(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003312 return NULL;
3313 }
3314
3315 //==- High-level Monitor -----------------------------------------------==//
3316 case IntrinsicHelper::MonitorEnter: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003317 Expand_MonitorEnter(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003318 return NULL;
3319 }
3320 case IntrinsicHelper::MonitorExit: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003321 Expand_MonitorExit(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003322 return NULL;
3323 }
3324
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003325 //==- Shadow Frame -----------------------------------------------------==//
3326 case IntrinsicHelper::AllocaShadowFrame: {
3327 Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
3328 return NULL;
3329 }
3330 case IntrinsicHelper::SetShadowFrameEntry: {
3331 Expand_SetShadowFrameEntry(call_inst.getArgOperand(0),
3332 call_inst.getArgOperand(1));
3333 return NULL;
3334 }
3335 case IntrinsicHelper::PopShadowFrame: {
3336 Expand_PopShadowFrame();
3337 return NULL;
3338 }
3339 case IntrinsicHelper::UpdateDexPC: {
3340 Expand_UpdateDexPC(call_inst.getArgOperand(0));
3341 return NULL;
3342 }
TDYa127a1b21852012-07-23 03:20:39 -07003343
Logan Chien75e4b602012-07-23 14:24:12 -07003344 //==- Comparison -------------------------------------------------------==//
3345 case IntrinsicHelper::CmplFloat:
3346 case IntrinsicHelper::CmplDouble: {
3347 return Expand_FPCompare(call_inst.getArgOperand(0),
3348 call_inst.getArgOperand(1),
3349 false);
3350 }
3351 case IntrinsicHelper::CmpgFloat:
3352 case IntrinsicHelper::CmpgDouble: {
3353 return Expand_FPCompare(call_inst.getArgOperand(0),
3354 call_inst.getArgOperand(1),
3355 true);
3356 }
3357 case IntrinsicHelper::CmpLong: {
3358 return Expand_LongCompare(call_inst.getArgOperand(0),
3359 call_inst.getArgOperand(1));
3360 }
TDYa127a1b21852012-07-23 03:20:39 -07003361
Logan Chien75e4b602012-07-23 14:24:12 -07003362 //==- Switch -----------------------------------------------------------==//
3363 case greenland::IntrinsicHelper::SparseSwitch: {
TDYa1275e869b62012-07-25 00:45:39 -07003364 // Nothing to be done.
Logan Chien75e4b602012-07-23 14:24:12 -07003365 return NULL;
3366 }
3367 case greenland::IntrinsicHelper::PackedSwitch: {
TDYa1275e869b62012-07-25 00:45:39 -07003368 // Nothing to be done.
Logan Chien75e4b602012-07-23 14:24:12 -07003369 return NULL;
3370 }
3371
3372 //==- Const ------------------------------------------------------------==//
Logan Chiend54a23d2012-07-24 11:19:23 -07003373 case greenland::IntrinsicHelper::ConstInt:
Logan Chien75e4b602012-07-23 14:24:12 -07003374 case greenland::IntrinsicHelper::ConstLong: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003375 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07003376 }
3377 case greenland::IntrinsicHelper::ConstFloat: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003378 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3379 irb_.getJFloatTy());
Logan Chien75e4b602012-07-23 14:24:12 -07003380 }
3381 case greenland::IntrinsicHelper::ConstDouble: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003382 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3383 irb_.getJDoubleTy());
3384 }
3385 case greenland::IntrinsicHelper::ConstObj: {
3386 LOG(FATAL) << "ConstObj should not occur at all";
Logan Chien75e4b602012-07-23 14:24:12 -07003387 return NULL;
3388 }
3389
3390 //==- Method Info ------------------------------------------------------==//
3391 case greenland::IntrinsicHelper::MethodInfo: {
TDYa1275e869b62012-07-25 00:45:39 -07003392 // Nothing to be done.
Logan Chien75e4b602012-07-23 14:24:12 -07003393 return NULL;
3394 }
3395
3396 //==- Copy -------------------------------------------------------------==//
Logan Chiend54a23d2012-07-24 11:19:23 -07003397 case greenland::IntrinsicHelper::CopyInt:
3398 case greenland::IntrinsicHelper::CopyFloat:
3399 case greenland::IntrinsicHelper::CopyLong:
TDYa1275e869b62012-07-25 00:45:39 -07003400 case greenland::IntrinsicHelper::CopyDouble:
Logan Chien75e4b602012-07-23 14:24:12 -07003401 case greenland::IntrinsicHelper::CopyObj: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003402 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07003403 }
3404
3405 //==- Shift ------------------------------------------------------------==//
3406 case greenland::IntrinsicHelper::SHLLong: {
3407 return Expand_IntegerShift(call_inst.getArgOperand(0),
3408 call_inst.getArgOperand(1),
3409 kIntegerSHL, kLong);
3410 }
3411 case greenland::IntrinsicHelper::SHRLong: {
3412 return Expand_IntegerShift(call_inst.getArgOperand(0),
3413 call_inst.getArgOperand(1),
3414 kIntegerSHR, kLong);
3415 }
3416 case greenland::IntrinsicHelper::USHRLong: {
3417 return Expand_IntegerShift(call_inst.getArgOperand(0),
3418 call_inst.getArgOperand(1),
3419 kIntegerUSHR, kLong);
3420 }
3421 case greenland::IntrinsicHelper::SHLInt: {
3422 return Expand_IntegerShift(call_inst.getArgOperand(0),
3423 call_inst.getArgOperand(1),
3424 kIntegerSHL, kInt);
3425 }
3426 case greenland::IntrinsicHelper::SHRInt: {
3427 return Expand_IntegerShift(call_inst.getArgOperand(0),
3428 call_inst.getArgOperand(1),
3429 kIntegerSHR, kInt);
3430 }
3431 case greenland::IntrinsicHelper::USHRInt: {
3432 return Expand_IntegerShift(call_inst.getArgOperand(0),
3433 call_inst.getArgOperand(1),
3434 kIntegerUSHR, kInt);
3435 }
3436
3437 //==- Conversion -------------------------------------------------------==//
TDYa127a1b21852012-07-23 03:20:39 -07003438 case IntrinsicHelper::IntToChar: {
3439 return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
3440 irb_.getJIntTy());
3441 }
3442 case IntrinsicHelper::IntToShort: {
3443 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
3444 irb_.getJIntTy());
3445 }
3446 case IntrinsicHelper::IntToByte: {
3447 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
3448 irb_.getJIntTy());
3449 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003450
Logan Chien75e4b602012-07-23 14:24:12 -07003451 //==- Unknown Cases ----------------------------------------------------==//
3452 case IntrinsicHelper::MaxIntrinsicId:
3453 case IntrinsicHelper::UnknownId:
3454 //default:
3455 // NOTE: "default" is intentionally commented so that C/C++ compiler will
3456 // give some warning on unmatched cases.
3457 // NOTE: We should not implement these cases.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003458 break;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003459 }
Logan Chien75e4b602012-07-23 14:24:12 -07003460 UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003461 return NULL;
3462}
3463
3464} // anonymous namespace
3465
3466namespace art {
3467namespace compiler_llvm {
3468
3469llvm::FunctionPass*
3470CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb) {
3471 return new GBCExpanderPass(intrinsic_helper, irb);
3472}
3473
3474} // namespace compiler_llvm
3475} // namespace art