blob: 672014cfd0966423471d2d1099fd33a124bf1d54 [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 // TODO: Init these fields
58 Compiler* compiler_;
59
60 const DexFile* dex_file_;
61 DexCache* dex_cache_;
62 const DexFile::CodeItem* code_item_;
63
64 OatCompilationUnit* oat_compilation_unit_;
65
66 uint32_t method_idx_;
67
68 llvm::Function* func_;
69
70 std::vector<llvm::BasicBlock*> basic_blocks_;
71
72 std::vector<llvm::BasicBlock*> basic_block_landing_pads_;
73 llvm::BasicBlock* basic_block_unwind_;
74
75 private:
Shih-wei Liao21d28f52012-06-12 05:55:00 -070076 //----------------------------------------------------------------------------
Logan Chien75e4b602012-07-23 14:24:12 -070077 // Constant for GBC expansion
78 //----------------------------------------------------------------------------
79 enum IntegerShiftKind {
80 kIntegerSHL,
81 kIntegerSHR,
82 kIntegerUSHR,
83 };
84
85 private:
86 //----------------------------------------------------------------------------
Shih-wei Liao21d28f52012-06-12 05:55:00 -070087 // Helper function for GBC expansion
88 //----------------------------------------------------------------------------
89
Shih-wei Liao21d28f52012-06-12 05:55:00 -070090 llvm::Value* ExpandToRuntime(runtime_support::RuntimeId rt,
91 llvm::CallInst& inst);
92
TDYa1275e869b62012-07-25 00:45:39 -070093 uint64_t LV2UInt(llvm::Value* lv) {
94 return llvm::cast<llvm::ConstantInt>(lv)->getZExtValue();
95 }
96
97 int64_t LV2SInt(llvm::Value* lv) {
98 return llvm::cast<llvm::ConstantInt>(lv)->getSExtValue();
99 }
100
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700101 private:
102 // TODO: Almost all Emit* are directly copy-n-paste from MethodCompiler.
103 // Refactor these utility functions from MethodCompiler to avoid forking.
104
105 bool EmitStackOverflowCheck(llvm::Instruction* first_non_alloca);
106
107 //----------------------------------------------------------------------------
108 // Dex cache code generation helper function
109 //----------------------------------------------------------------------------
110 llvm::Value* EmitLoadDexCacheAddr(MemberOffset dex_cache_offset);
111
112 llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
113
114 llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
115
116 llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
117
118 llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
119
120 //----------------------------------------------------------------------------
121 // Code generation helper function
122 //----------------------------------------------------------------------------
123 llvm::Value* EmitLoadMethodObjectAddr();
124
125 llvm::Value* EmitLoadArrayLength(llvm::Value* array);
126
127 llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
128
129 llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
130 llvm::Value* this_addr);
131
132 llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
133 llvm::Value* index_value,
134 JType elem_jty);
135
136 private:
137 //----------------------------------------------------------------------------
138 // Expand Greenland intrinsics
139 //----------------------------------------------------------------------------
140 void Expand_TestSuspend(llvm::CallInst& call_inst);
141
TDYa1279a129452012-07-19 03:10:08 -0700142 void Expand_MarkGCCard(llvm::CallInst& call_inst);
143
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700144 llvm::Value* Expand_GetException();
145
146 llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
147
148 llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
149
150 void Expand_LockObject(llvm::Value* obj);
151
152 void Expand_UnlockObject(llvm::Value* obj);
153
154 llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
155 llvm::Value* index_value,
156 JType elem_jty);
157
158 void Expand_ArrayPut(llvm::Value* new_value,
159 llvm::Value* array_addr,
160 llvm::Value* index_value,
161 JType elem_jty);
162
163 void Expand_FilledNewArray(llvm::CallInst& call_inst);
164
165 llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
166 llvm::Value* is_volatile_value,
167 llvm::Value* object_addr,
168 JType field_jty);
169
170 void Expand_IPutFast(llvm::Value* field_offset_value,
171 llvm::Value* is_volatile_value,
172 llvm::Value* object_addr,
173 llvm::Value* new_value,
174 JType field_jty);
175
176 llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
177 llvm::Value* field_offset_value,
178 llvm::Value* is_volatile_value,
179 JType field_jty);
180
181 void Expand_SPutFast(llvm::Value* static_storage_addr,
182 llvm::Value* field_offset_value,
183 llvm::Value* is_volatile_value,
184 llvm::Value* new_value,
185 JType field_jty);
186
187 llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
188
189 llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
190
191 llvm::Value*
192 Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
193
194 llvm::Value*
195 Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
196 llvm::Value* this_addr);
197
198 llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
199
TDYa1274ec8ccd2012-08-11 07:04:57 -0700200 llvm::Value* Expand_DivRem(llvm::CallInst& call_inst, bool is_div, JType op_jty);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700201
202 void Expand_AllocaShadowFrame(llvm::Value* num_entry_value);
203
204 void Expand_SetShadowFrameEntry(llvm::Value* obj, llvm::Value* entry_idx);
205
206 void Expand_PopShadowFrame();
207
208 void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
209
TDYa127a1b21852012-07-23 03:20:39 -0700210 //----------------------------------------------------------------------------
211 // Quick
212 //----------------------------------------------------------------------------
213
214 llvm::Value* Expand_FPCompare(llvm::Value* src1_value,
215 llvm::Value* src2_value,
216 bool gt_bias);
217
218 llvm::Value* Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value);
219
220 llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
221 llvm::Value* cmp_lt);
222
TDYa1275e869b62012-07-25 00:45:39 -0700223 class ScopedExpandToBasicBlock {
224 public:
225 ScopedExpandToBasicBlock(IRBuilder& irb, llvm::Instruction* expand_inst)
226 : irb_(irb), expand_inst_(expand_inst) {
227 llvm::Function* func = expand_inst_->getParent()->getParent();
228 begin_bb_ = llvm::BasicBlock::Create(irb_.getContext(),
229 "",
230 func);
231 irb_.SetInsertPoint(begin_bb_);
232 }
233
234 ~ScopedExpandToBasicBlock() {
235 llvm::BasicBlock* end_bb = irb_.GetInsertBlock();
236 SplitAndInsertBasicBlocksAfter(*expand_inst_, begin_bb_, end_bb);
237 }
238
239 private:
240 // Split the basic block containing INST at INST and insert a sequence of
241 // basic blocks with a single entry at BEGIN_BB and a single exit at END_BB
242 // before INST.
243 llvm::BasicBlock*
244 SplitAndInsertBasicBlocksAfter(llvm::BasicBlock::iterator inst,
245 llvm::BasicBlock* begin_bb,
246 llvm::BasicBlock* end_bb);
247 private:
248 IRBuilder& irb_;
249 llvm::Instruction* expand_inst_;
250 llvm::BasicBlock* begin_bb_;
251 };
252
TDYa127f71bf5a2012-07-29 20:09:52 -0700253 llvm::Value* EmitLoadConstantClass(uint32_t dex_pc, uint32_t type_idx);
TDYa1275a26d442012-07-26 18:58:38 -0700254 llvm::Value* EmitLoadStaticStorage(uint32_t dex_pc, uint32_t type_idx);
255
TDYa1275e869b62012-07-25 00:45:39 -0700256 llvm::Value* Expand_HLIGet(llvm::CallInst& call_inst, JType field_jty);
257 void Expand_HLIPut(llvm::CallInst& call_inst, JType field_jty);
258
TDYa1275a26d442012-07-26 18:58:38 -0700259 llvm::Value* Expand_HLSget(llvm::CallInst& call_inst, JType field_jty);
260 void Expand_HLSput(llvm::CallInst& call_inst, JType field_jty);
261
262 llvm::Value* Expand_HLArrayGet(llvm::CallInst& call_inst, JType field_jty);
263 void Expand_HLArrayPut(llvm::CallInst& call_inst, JType field_jty);
264
TDYa127f71bf5a2012-07-29 20:09:52 -0700265 llvm::Value* Expand_ConstString(llvm::CallInst& call_inst);
266 llvm::Value* Expand_ConstClass(llvm::CallInst& call_inst);
267
268 void Expand_MonitorEnter(llvm::CallInst& call_inst);
269 void Expand_MonitorExit(llvm::CallInst& call_inst);
270
271 void Expand_HLCheckCast(llvm::CallInst& call_inst);
272 llvm::Value* Expand_InstanceOf(llvm::CallInst& call_inst);
273
274 llvm::Value* Expand_NewInstance(llvm::CallInst& call_inst);
275
276 llvm::Value* Expand_HLInvoke(llvm::CallInst& call_inst);
277
278 llvm::Value* Expand_OptArrayLength(llvm::CallInst& call_inst);
279 llvm::Value* Expand_NewArray(llvm::CallInst& call_inst);
280 llvm::Value* Expand_HLFilledNewArray(llvm::CallInst& call_inst);
281 void Expand_HLFillArrayData(llvm::CallInst& call_inst);
282
283 llvm::Value* EmitAllocNewArray(uint32_t dex_pc,
284 llvm::Value* array_length_value,
285 uint32_t type_idx,
286 bool is_filled_new_array);
287
288 llvm::Value* EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
289 InvokeType invoke_type,
290 llvm::Value* this_addr,
291 uint32_t dex_pc,
292 bool is_fast_path);
293
TDYa1275e869b62012-07-25 00:45:39 -0700294 void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
295
296 void EmitUpdateDexPC(uint32_t dex_pc);
297
298 void EmitGuard_DivZeroException(uint32_t dex_pc,
299 llvm::Value* denominator,
300 JType op_jty);
301
302 void EmitGuard_NullPointerException(uint32_t dex_pc,
303 llvm::Value* object);
304
305 void EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
306 llvm::Value* array,
307 llvm::Value* index);
308
309 void EmitGuard_ArrayException(uint32_t dex_pc,
310 llvm::Value* array,
311 llvm::Value* index);
312
313 llvm::FunctionType* GetFunctionType(uint32_t method_idx, bool is_static);
314
315 llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
316
317 llvm::BasicBlock* CreateBasicBlockWithDexPC(uint32_t dex_pc,
318 const char* postfix);
319
320 int32_t GetTryItemOffset(uint32_t dex_pc);
321
322 llvm::BasicBlock* GetLandingPadBasicBlock(uint32_t dex_pc);
323
324 llvm::BasicBlock* GetUnwindBasicBlock();
325
326 void EmitGuard_ExceptionLandingPad(uint32_t dex_pc);
327
328 void EmitBranchExceptionLandingPad(uint32_t dex_pc);
329
Logan Chien75e4b602012-07-23 14:24:12 -0700330 //----------------------------------------------------------------------------
331 // Expand Arithmetic Helper Intrinsics
332 //----------------------------------------------------------------------------
333
334 llvm::Value* Expand_IntegerShift(llvm::Value* src1_value,
335 llvm::Value* src2_value,
336 IntegerShiftKind kind,
337 JType op_jty);
338
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700339 public:
340 static char ID;
341
342 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb)
343 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
344 context_(irb.getContext()), rtb_(irb.Runtime())
345 { }
346
347 bool runOnFunction(llvm::Function& func);
348
349 private:
350 bool InsertStackOverflowCheck(llvm::Function& func);
351
352 llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
353 llvm::CallInst& call_inst);
354
355};
356
357char GBCExpanderPass::ID = 0;
358
359bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
TDYa127b672d1e2012-06-28 21:21:45 -0700360 // Runtime support or stub
361 if (func.getName().startswith("art_") || func.getName().startswith("Art")) {
362 return false;
363 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700364 bool changed;
365
TDYa127b672d1e2012-06-28 21:21:45 -0700366 // TODO: Use intrinsic.
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700367 changed = InsertStackOverflowCheck(func);
368
369 std::list<std::pair<llvm::CallInst*,
370 IntrinsicHelper::IntrinsicId> > work_list;
371
372 for (llvm::inst_iterator inst_iter = llvm::inst_begin(func),
373 inst_end = llvm::inst_end(func); inst_iter != inst_end; inst_iter++) {
374 // Only CallInst with its called function is dexlang intrinsic need to
375 // process
376 llvm::Instruction* inst = &*inst_iter;
377 if (llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst)) {
378 const llvm::Function* callee = call_inst->getCalledFunction();
379
380 if (callee != NULL) {
381 IntrinsicHelper::IntrinsicId intr_id =
382 intrinsic_helper_.GetIntrinsicId(callee);
383
384 if (intr_id != IntrinsicHelper::UnknownId) {
385 work_list.push_back(std::make_pair(call_inst, intr_id));
386 }
387 }
388 }
389 }
390
391 changed |= !work_list.empty();
392
393 shadow_frame_ = NULL;
394 old_shadow_frame_ = NULL;
395 shadow_frame_size_ = 0;
TDYa1275e869b62012-07-25 00:45:39 -0700396 func_ = &func;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700397
398 // Remove the instruction containing in the work_list
399 while (!work_list.empty()) {
400 llvm::CallInst* intr_inst = work_list.front().first;
401 IntrinsicHelper::IntrinsicId intr_id = work_list.front().second;
402
403 // Remove the instruction from work list
404 work_list.pop_front();
405
406 // Move the IRBuilder insert pointer
407 irb_.SetInsertPoint(intr_inst);
408
409 // Process the expansion
410 llvm::Value* new_value = ExpandIntrinsic(intr_id, *intr_inst);
411
412 // Use the new value from the expansion
413 if (new_value != NULL) {
414 intr_inst->replaceAllUsesWith(new_value);
415 }
416
417 // Remove the intrinsic instruction
418 intr_inst->eraseFromParent();
419 }
420
421 VERIFY_LLVM_FUNCTION(func);
422
423 return changed;
424}
425
426llvm::BasicBlock*
TDYa1275e869b62012-07-25 00:45:39 -0700427GBCExpanderPass::ScopedExpandToBasicBlock::
428SplitAndInsertBasicBlocksAfter(llvm::BasicBlock::iterator inst,
429 llvm::BasicBlock* begin_bb,
430 llvm::BasicBlock* end_bb) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700431 llvm::BasicBlock* original = inst->getParent();
432 llvm::Function* parent = original->getParent();
433
434 // 1. Create a new basic block A after ORIGINAL
435 llvm::BasicBlock *insert_before =
436 llvm::next(llvm::Function::iterator(original)).getNodePtrUnchecked();
437 llvm::BasicBlock* a =
TDYa1275e869b62012-07-25 00:45:39 -0700438 llvm::BasicBlock::Create(irb_.getContext(), "", parent, insert_before);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700439
440 // 2. Move all instructions in ORIGINAL after INST (included) to A
441 a->getInstList().splice(a->end(), original->getInstList(),
442 inst, original->end());
443
444 // 3. Add an unconditional branch in ORIGINAL to begin_bb
445 llvm::BranchInst::Create(begin_bb, original);
446
447 // 4. Add an unconditional branch in END_BB to A
448 llvm::BranchInst::Create(a, end_bb);
449
450 // 5. Update the PHI nodes in the successors of A. Update the PHI node entry
451 // with incoming basic block from ORIGINAL to A
452 for (llvm::succ_iterator succ_iter = llvm::succ_begin(a),
453 succ_end = llvm::succ_end(a); succ_iter != succ_end; succ_iter++) {
454 llvm::BasicBlock* succ = *succ_iter;
455 llvm::PHINode* phi;
456 for (llvm::BasicBlock::iterator inst_iter = succ->begin();
457 (phi = llvm::dyn_cast<llvm::PHINode>(inst_iter)); ++inst_iter) {
458 int idx;
459 while ((idx = phi->getBasicBlockIndex(original)) != -1) {
460 phi->setIncomingBlock(static_cast<unsigned>(idx), a);
461 }
462 }
463 }
464
465 return a;
466}
467
468llvm::Value* GBCExpanderPass::ExpandToRuntime(runtime_support::RuntimeId rt,
469 llvm::CallInst& inst) {
470 // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
471 // the arguments passed to the GBC intrinsic are as the same as IBC runtime
472 // function, therefore only called function is needed to change.
473 unsigned num_args = inst.getNumArgOperands();
474
475 if (num_args <= 0) {
476 return irb_.CreateCall(irb_.GetRuntime(rt));
477 } else {
478 std::vector<llvm::Value*> args;
479 for (unsigned i = 0; i < num_args; i++) {
480 args.push_back(inst.getArgOperand(i));
481 }
482
483 return irb_.CreateCall(irb_.GetRuntime(rt), args);
484 }
485}
486
487bool
488GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
TDYa1275e869b62012-07-25 00:45:39 -0700489 ScopedExpandToBasicBlock eb(irb_, first_non_alloca);
490
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700491 llvm::Function* func = first_non_alloca->getParent()->getParent();
492 llvm::Module* module = func->getParent();
493
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700494 // Call llvm intrinsic function to get frame address.
495 llvm::Function* frameaddress =
496 llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
497
498 // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
499 llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
500
501 // Cast i8* to int
502 frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
503
504 // Get thread.stack_end_
505 llvm::Value* stack_end =
506 irb_.Runtime().EmitLoadFromThreadOffset(Thread::StackEndOffset().Int32Value(),
507 irb_.getPtrEquivIntTy(),
508 kTBAARuntimeInfo);
509
510 // Check the frame address < thread.stack_end_ ?
511 llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
512
513 llvm::BasicBlock* block_exception =
514 llvm::BasicBlock::Create(context_, "stack_overflow", func);
515
516 llvm::BasicBlock* block_continue =
517 llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
518
519 irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
520
521 // If stack overflow, throw exception.
522 irb_.SetInsertPoint(block_exception);
523 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowStackOverflowException));
524
525 // Unwind.
526 llvm::Type* ret_type = func->getReturnType();
527 if (ret_type->isVoidTy()) {
528 irb_.CreateRetVoid();
529 } else {
530 // The return value is ignored when there's an exception. MethodCompiler
531 // returns zero value under the the corresponding return type in this case.
532 // GBCExpander returns LLVM undef value here for brevity
533 irb_.CreateRet(llvm::UndefValue::get(ret_type));
534 }
535
536 irb_.SetInsertPoint(block_continue);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700537 return true;
538}
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) {
TDYa1275e869b62012-07-25 00:45:39 -0700663 ScopedExpandToBasicBlock eb(irb_, &call_inst);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700664 irb_.Runtime().EmitTestSuspend();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700665 return;
666}
667
TDYa1279a129452012-07-19 03:10:08 -0700668void GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
TDYa1275e869b62012-07-25 00:45:39 -0700669 ScopedExpandToBasicBlock eb(irb_, &call_inst);
TDYa1279a129452012-07-19 03:10:08 -0700670 irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
TDYa1279a129452012-07-19 03:10:08 -0700671 return;
672}
673
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700674llvm::Value* GBCExpanderPass::Expand_GetException() {
675 // Get thread-local exception field address
676 llvm::Value* exception_object_addr =
677 irb_.Runtime().EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
678 irb_.getJObjectTy(),
679 kTBAAJRuntime);
680
681 // Set thread-local exception field address to NULL
682 irb_.Runtime().EmitStoreToThreadOffset(Thread::ExceptionOffset().Int32Value(),
683 irb_.getJNull(),
684 kTBAAJRuntime);
685
686 return exception_object_addr;
687}
688
689llvm::Value*
690GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
691 uint32_t string_idx =
692 llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
693
694 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
695
696 return irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
697}
698
699llvm::Value*
700GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
701 uint32_t type_idx =
702 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
703
704 llvm::Value* type_field_addr =
705 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
706
707 return irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
708}
709
710void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
TDYa1275e869b62012-07-25 00:45:39 -0700711 ScopedExpandToBasicBlock eb(irb_, irb_.GetInsertPoint());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700712 rtb_.EmitLockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700713 return;
714}
715
716void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
TDYa1275e869b62012-07-25 00:45:39 -0700717 ScopedExpandToBasicBlock eb(irb_, irb_.GetInsertPoint());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700718 rtb_.EmitUnlockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700719 return;
720}
721
722llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
723 llvm::Value* index_value,
724 JType elem_jty) {
725 llvm::Value* array_elem_addr =
726 EmitArrayGEP(array_addr, index_value, elem_jty);
727
728 return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
729}
730
731void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
732 llvm::Value* array_addr,
733 llvm::Value* index_value,
734 JType elem_jty) {
735 llvm::Value* array_elem_addr =
736 EmitArrayGEP(array_addr, index_value, elem_jty);
737
738 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
739
740 return;
741}
742
743void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
744 // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
745 llvm::Value* array = call_inst.getArgOperand(0);
746
747 uint32_t element_jty =
748 llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
749
750 DCHECK(call_inst.getNumArgOperands() > 2);
751 unsigned num_elements = (call_inst.getNumArgOperands() - 2);
752
753 bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
754
755 uint32_t alignment;
756 llvm::Constant* elem_size;
757 llvm::PointerType* field_type;
758
759 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
760 // as the element, thus we are only checking 2 cases: primitive int and
761 // non-primitive type.
762 if (is_elem_int_ty) {
763 alignment = sizeof(int32_t);
764 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
765 field_type = irb_.getJIntTy()->getPointerTo();
766 } else {
767 alignment = irb_.getSizeOfPtrEquivInt();
768 elem_size = irb_.getSizeOfPtrEquivIntValue();
769 field_type = irb_.getJObjectTy()->getPointerTo();
770 }
771
772 llvm::Value* data_field_offset =
773 irb_.getPtrEquivInt(Array::DataOffset(alignment).Int32Value());
774
775 llvm::Value* data_field_addr =
776 irb_.CreatePtrDisp(array, data_field_offset, field_type);
777
778 for (unsigned i = 0; i < num_elements; ++i) {
779 // Values to fill the array begin at the 3rd argument
780 llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
781
782 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
783
784 data_field_addr =
785 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
786 }
787
788 return;
789}
790
791llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
792 llvm::Value* /*is_volatile_value*/,
793 llvm::Value* object_addr,
794 JType field_jty) {
795 int field_offset =
796 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
797
798 DCHECK_GE(field_offset, 0);
799
800 llvm::PointerType* field_type =
801 irb_.getJType(field_jty, kField)->getPointerTo();
802
803 field_offset_value = irb_.getPtrEquivInt(field_offset);
804
805 llvm::Value* field_addr =
806 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
807
808 // TODO: Check is_volatile. We need to generate atomic load instruction
809 // when is_volatile is true.
810 return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
811}
812
813void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
814 llvm::Value* /* is_volatile_value */,
815 llvm::Value* object_addr,
816 llvm::Value* new_value,
817 JType field_jty) {
818 int field_offset =
819 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
820
821 DCHECK_GE(field_offset, 0);
822
823 llvm::PointerType* field_type =
824 irb_.getJType(field_jty, kField)->getPointerTo();
825
826 field_offset_value = irb_.getPtrEquivInt(field_offset);
827
828 llvm::Value* field_addr =
829 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
830
831 // TODO: Check is_volatile. We need to generate atomic store instruction
832 // when is_volatile is true.
833 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
834
835 return;
836}
837
838llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
839 llvm::Value* field_offset_value,
840 llvm::Value* /*is_volatile_value*/,
841 JType field_jty) {
842 int field_offset =
843 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
844
845 DCHECK_GE(field_offset, 0);
846
847 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
848
849 llvm::Value* static_field_addr =
850 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
851 irb_.getJType(field_jty, kField)->getPointerTo());
852
853 // TODO: Check is_volatile. We need to generate atomic store instruction
854 // when is_volatile is true.
855 return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
856}
857
858void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
859 llvm::Value* field_offset_value,
860 llvm::Value* /* is_volatile_value */,
861 llvm::Value* new_value,
862 JType field_jty) {
863 int field_offset =
864 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
865
866 DCHECK_GE(field_offset, 0);
867
868 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
869
870 llvm::Value* static_field_addr =
871 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
872 irb_.getJType(field_jty, kField)->getPointerTo());
873
874 // TODO: Check is_volatile. We need to generate atomic store instruction
875 // when is_volatile is true.
876 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
877
878 return;
879}
880
881llvm::Value*
882GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
883 return irb_.LoadFromObjectOffset(method_object_addr,
884 Method::DeclaringClassOffset().Int32Value(),
885 irb_.getJObjectTy(),
886 kTBAAConstJObject);
887}
888
889llvm::Value*
890GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
891 uint32_t type_idx =
892 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
893
894 llvm::Value* storage_field_addr =
895 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
896
897 return irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
898}
899
900llvm::Value*
901GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
902 uint32_t callee_method_idx =
903 llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
904
905 return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
906}
907
908llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
909 llvm::Value* vtable_idx_value,
910 llvm::Value* this_addr) {
911 int vtable_idx =
912 llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
913
914 return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
915}
916
917llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
918 // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
919 llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
920 unsigned num_args = call_inst.getNumArgOperands();
921 llvm::Type* ret_type = call_inst.getType();
922
923 // Determine the function type of the callee method
924 std::vector<llvm::Type*> args_type;
925 std::vector<llvm::Value*> args;
926 for (unsigned i = 0; i < num_args; i++) {
927 args.push_back(call_inst.getArgOperand(i));
928 args_type.push_back(args[i]->getType());
929 }
930
931 llvm::FunctionType* callee_method_type =
932 llvm::FunctionType::get(ret_type, args_type, false);
933
934 llvm::Value* code_addr =
935 irb_.LoadFromObjectOffset(callee_method_object_addr,
936 Method::GetCodeOffset().Int32Value(),
937 callee_method_type->getPointerTo(),
938 kTBAAJRuntime);
939
940 // Invoke callee
941 llvm::Value* retval = irb_.CreateCall(code_addr, args);
942
943 return retval;
944}
945
TDYa1274ec8ccd2012-08-11 07:04:57 -0700946llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::CallInst& call_inst,
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700947 bool is_div, JType op_jty) {
TDYa1274ec8ccd2012-08-11 07:04:57 -0700948 llvm::Value* dividend = call_inst.getArgOperand(0);
949 llvm::Value* divisor = call_inst.getArgOperand(1);
950#if defined(ART_USE_QUICK_COMPILER)
951 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
952 EmitGuard_DivZeroException(dex_pc, divisor, op_jty);
953#endif
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700954 // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
955
956 // Check the special case: MININT / -1 = MININT
957 // That case will cause overflow, which is undefined behavior in llvm.
958 // So we check the divisor is -1 or not, if the divisor is -1, we do
959 // the special path to avoid undefined behavior.
960 llvm::Type* op_type = irb_.getJType(op_jty, kAccurate);
961 llvm::Value* zero = irb_.getJZero(op_jty);
962 llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
963
TDYa1275e869b62012-07-25 00:45:39 -0700964 ScopedExpandToBasicBlock eb(irb_, irb_.GetInsertPoint());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700965
TDYa1275e869b62012-07-25 00:45:39 -0700966 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700967 llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
968 llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
969 llvm::BasicBlock* neg_one_cont =
970 llvm::BasicBlock::Create(context_, "", parent);
971
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700972 llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
973 irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
974
975 // If divisor == -1
976 irb_.SetInsertPoint(eq_neg_one);
977 llvm::Value* eq_result;
978 if (is_div) {
979 // We can just change from "dividend div -1" to "neg dividend". The sub
980 // don't care the sign/unsigned because of two's complement representation.
981 // And the behavior is what we want:
982 // -(2^n) (2^n)-1
983 // MININT < k <= MAXINT -> mul k -1 = -k
984 // MININT == k -> mul k -1 = k
985 //
986 // LLVM use sub to represent 'neg'
987 eq_result = irb_.CreateSub(zero, dividend);
988 } else {
989 // Everything modulo -1 will be 0.
990 eq_result = zero;
991 }
992 irb_.CreateBr(neg_one_cont);
993
994 // If divisor != -1, just do the division.
995 irb_.SetInsertPoint(ne_neg_one);
996 llvm::Value* ne_result;
997 if (is_div) {
998 ne_result = irb_.CreateSDiv(dividend, divisor);
999 } else {
1000 ne_result = irb_.CreateSRem(dividend, divisor);
1001 }
1002 irb_.CreateBr(neg_one_cont);
1003
1004 irb_.SetInsertPoint(neg_one_cont);
1005 llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
1006 result->addIncoming(eq_result, eq_neg_one);
1007 result->addIncoming(ne_result, ne_neg_one);
1008
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001009 return result;
1010}
1011
1012void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value) {
1013 // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
1014 // MethodCompiler::EmitPushShadowFrame
1015 shadow_frame_size_ =
1016 llvm::cast<llvm::ConstantInt>(num_entry_value)->getZExtValue();
1017
1018 llvm::StructType* shadow_frame_type =
1019 irb_.getShadowFrameTy(shadow_frame_size_);
1020
1021 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
1022
1023 // Alloca a pointer to old shadow frame
1024 old_shadow_frame_ =
1025 irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
1026
1027 // Zero-initialization of the shadow frame table
1028 llvm::Value* shadow_frame_table =
1029 irb_.CreateConstGEP2_32(shadow_frame_, 0, 1);
1030 llvm::Type* table_type = shadow_frame_type->getElementType(1);
1031
1032 llvm::ConstantAggregateZero* zero_initializer =
1033 llvm::ConstantAggregateZero::get(table_type);
1034
1035 irb_.CreateStore(zero_initializer, shadow_frame_table, kTBAAShadowFrame);
1036
1037 // Push the shadow frame
1038 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1039
1040 // Push the shadow frame
1041 llvm::Value* shadow_frame_upcast =
1042 irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
1043
1044 llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
1045 method_object_addr,
1046 shadow_frame_size_);
1047
1048 irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
1049
1050 return;
1051}
1052
1053void GBCExpanderPass::Expand_SetShadowFrameEntry(llvm::Value* obj,
1054 llvm::Value* entry_idx) {
1055 DCHECK(shadow_frame_ != NULL);
1056
1057 llvm::Value* gep_index[] = {
1058 irb_.getInt32(0), // No pointer displacement
1059 irb_.getInt32(1), // SIRT
1060 entry_idx // Pointer field
1061 };
1062
1063 llvm::Value* entry_addr = irb_.CreateGEP(shadow_frame_, gep_index);
1064 irb_.CreateStore(obj, entry_addr, kTBAAShadowFrame);
1065 return;
1066}
1067
1068void GBCExpanderPass::Expand_PopShadowFrame() {
1069 rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
1070 return;
1071}
1072
1073void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
1074 irb_.StoreToObjectOffset(shadow_frame_,
1075 ShadowFrame::DexPCOffset(),
1076 dex_pc_value,
1077 kTBAAShadowFrame);
1078 return;
1079}
1080
1081bool GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
1082 // DexLang generates all alloca instruction in the first basic block of the
1083 // FUNC and also there's no any alloca instructions after the first non-alloca
1084 // instruction
1085
1086 llvm::BasicBlock::iterator first_non_alloca = func.front().begin();
1087 while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
1088 ++first_non_alloca;
1089 }
1090
1091 // Insert stack overflow check codes before first_non_alloca (i.e., after all
1092 // alloca instructions)
1093 return EmitStackOverflowCheck(&*first_non_alloca);
1094}
1095
TDYa1275e869b62012-07-25 00:45:39 -07001096// ==== High-level intrinsic expander ==========================================
1097
TDYa127a1b21852012-07-23 03:20:39 -07001098llvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
1099 llvm::Value* src2_value,
1100 bool gt_bias) {
1101 llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
1102 llvm::Value* cmp_lt;
1103
1104 if (gt_bias) {
1105 cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
1106 } else {
1107 cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
1108 }
1109
1110 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1111}
1112
1113llvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
1114 llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
1115 llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
1116
1117 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1118}
1119
1120llvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
1121 llvm::Value* cmp_lt) {
1122
1123 llvm::Constant* zero = irb_.getJInt(0);
1124 llvm::Constant* pos1 = irb_.getJInt(1);
1125 llvm::Constant* neg1 = irb_.getJInt(-1);
1126
1127 llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
1128 llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
1129
1130 return result_eq;
1131}
1132
Logan Chien75e4b602012-07-23 14:24:12 -07001133llvm::Value* GBCExpanderPass::Expand_IntegerShift(llvm::Value* src1_value,
1134 llvm::Value* src2_value,
1135 IntegerShiftKind kind,
1136 JType op_jty) {
1137 DCHECK(op_jty == kInt || op_jty == kLong);
1138
1139 // Mask and zero-extend RHS properly
1140 if (op_jty == kInt) {
1141 src2_value = irb_.CreateAnd(src2_value, 0x1f);
1142 } else {
1143 llvm::Value* masked_src2_value = irb_.CreateAnd(src2_value, 0x3f);
1144 src2_value = irb_.CreateZExt(masked_src2_value, irb_.getJLongTy());
1145 }
1146
1147 // Create integer shift llvm instruction
1148 switch (kind) {
1149 case kIntegerSHL:
1150 return irb_.CreateShl(src1_value, src2_value);
1151
1152 case kIntegerSHR:
1153 return irb_.CreateAShr(src1_value, src2_value);
1154
1155 case kIntegerUSHR:
1156 return irb_.CreateLShr(src1_value, src2_value);
1157
1158 default:
1159 LOG(FATAL) << "Unknown integer shift kind: " << kind;
1160 return NULL;
1161 }
1162}
1163
TDYa1275a26d442012-07-26 18:58:38 -07001164llvm::Value* GBCExpanderPass::Expand_HLArrayGet(llvm::CallInst& call_inst,
1165 JType elem_jty) {
1166 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1167
1168 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1169 llvm::Value* array_addr = call_inst.getArgOperand(1);
1170 llvm::Value* index_value = call_inst.getArgOperand(2);
1171
1172 // TODO: opt_flags
1173 EmitGuard_ArrayException(dex_pc, array_addr, index_value);
1174
1175 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1176
1177 llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
1178
1179 switch (elem_jty) {
1180 case kVoid:
1181 break;
1182
1183 case kBoolean:
1184 case kChar:
1185 array_elem_value = irb_.CreateZExt(array_elem_value, irb_.getJType(elem_jty, kReg));
1186 break;
1187
1188 case kByte:
1189 case kShort:
1190 array_elem_value = irb_.CreateSExt(array_elem_value, irb_.getJType(elem_jty, kReg));
1191 break;
1192
1193 case kInt:
1194 case kLong:
1195 case kFloat:
1196 case kDouble:
1197 case kObject:
1198 break;
1199
1200 default:
1201 LOG(FATAL) << "Unknown java type: " << elem_jty;
1202 }
1203
1204 return array_elem_value;
1205}
1206
1207
1208void GBCExpanderPass::Expand_HLArrayPut(llvm::CallInst& call_inst,
1209 JType elem_jty) {
1210 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1211
1212 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1213 llvm::Value* new_value = call_inst.getArgOperand(1);
1214 llvm::Value* array_addr = call_inst.getArgOperand(2);
1215 llvm::Value* index_value = call_inst.getArgOperand(3);
1216
1217 // TODO: opt_flags
1218 EmitGuard_ArrayException(dex_pc, array_addr, index_value);
1219
1220 switch (elem_jty) {
1221 case kVoid:
1222 break;
1223
1224 case kBoolean:
1225 case kChar:
1226 new_value = irb_.CreateTrunc(new_value, irb_.getJType(elem_jty, kArray));
1227 break;
1228
1229 case kInt:
1230 case kLong:
1231 case kFloat:
1232 case kDouble:
1233 case kObject:
1234 break;
1235
1236 default:
1237 LOG(FATAL) << "Unknown java type: " << elem_jty;
1238 }
1239
1240 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1241
1242 if (elem_jty == kObject) { // If put an object, check the type, and mark GC card table.
1243 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::CheckPutArrayElement);
1244
1245 irb_.CreateCall2(runtime_func, new_value, array_addr);
1246
1247 EmitGuard_ExceptionLandingPad(dex_pc);
1248
1249 EmitMarkGCCard(new_value, array_addr);
1250 }
1251
1252 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
1253
1254 return;
1255}
1256
TDYa1275e869b62012-07-25 00:45:39 -07001257llvm::Value* GBCExpanderPass::Expand_HLIGet(llvm::CallInst& call_inst,
1258 JType field_jty) {
1259 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1260
1261 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1262 llvm::Value* object_addr = call_inst.getArgOperand(1);
1263 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(2));
1264
1265 // TODO: opt_flags
1266 EmitGuard_NullPointerException(dex_pc, object_addr);
1267
1268 llvm::Value* field_value;
1269
1270 int field_offset;
1271 bool is_volatile;
1272 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1273 field_idx, oat_compilation_unit_, field_offset, is_volatile, false);
1274
1275 if (!is_fast_path) {
1276 llvm::Function* runtime_func;
1277
1278 if (field_jty == kObject) {
1279 runtime_func = irb_.GetRuntime(runtime_support::GetObjectInstance);
1280 } else if (field_jty == kLong || field_jty == kDouble) {
1281 runtime_func = irb_.GetRuntime(runtime_support::Get64Instance);
1282 } else {
1283 runtime_func = irb_.GetRuntime(runtime_support::Get32Instance);
1284 }
1285
1286 llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
1287
1288 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1289
1290 EmitUpdateDexPC(dex_pc);
1291
1292 field_value = irb_.CreateCall3(runtime_func, field_idx_value,
1293 method_object_addr, object_addr);
1294
1295 EmitGuard_ExceptionLandingPad(dex_pc);
1296
1297 } else {
1298 DCHECK_GE(field_offset, 0);
1299
1300 llvm::PointerType* field_type =
1301 irb_.getJType(field_jty, kField)->getPointerTo();
1302
1303 llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
1304
1305 llvm::Value* field_addr =
1306 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1307
1308 // TODO: Check is_volatile. We need to generate atomic load instruction
1309 // when is_volatile is true.
1310 field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
1311 }
1312
1313 if (field_jty == kFloat || field_jty == kDouble) {
TDYa1275a26d442012-07-26 18:58:38 -07001314 field_value = irb_.CreateBitCast(field_value, irb_.getJType(field_jty, kAccurate));
TDYa1275e869b62012-07-25 00:45:39 -07001315 }
1316
1317 return field_value;
1318}
1319
1320void GBCExpanderPass::Expand_HLIPut(llvm::CallInst& call_inst,
1321 JType field_jty) {
1322 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1323
1324 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1325 llvm::Value* object_addr = call_inst.getArgOperand(1);
1326 llvm::Value* new_value = call_inst.getArgOperand(2);
1327 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(3));
1328
1329 if (field_jty == kFloat || field_jty == kDouble) {
TDYa1275a26d442012-07-26 18:58:38 -07001330 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty, kField));
TDYa1275e869b62012-07-25 00:45:39 -07001331 }
1332
1333 // TODO: opt_flags
1334 EmitGuard_NullPointerException(dex_pc, object_addr);
1335
1336 int field_offset;
1337 bool is_volatile;
1338 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1339 field_idx, oat_compilation_unit_, field_offset, is_volatile, true);
1340
1341 if (!is_fast_path) {
1342 llvm::Function* runtime_func;
1343
1344 if (field_jty == kObject) {
1345 runtime_func = irb_.GetRuntime(runtime_support::SetObjectInstance);
1346 } else if (field_jty == kLong || field_jty == kDouble) {
1347 runtime_func = irb_.GetRuntime(runtime_support::Set64Instance);
1348 } else {
1349 runtime_func = irb_.GetRuntime(runtime_support::Set32Instance);
1350 }
1351
1352 llvm::Value* field_idx_value = irb_.getInt32(field_idx);
1353
1354 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1355
1356 EmitUpdateDexPC(dex_pc);
1357
1358 irb_.CreateCall4(runtime_func, field_idx_value,
1359 method_object_addr, object_addr, new_value);
1360
1361 EmitGuard_ExceptionLandingPad(dex_pc);
1362
1363 } else {
1364 DCHECK_GE(field_offset, 0);
1365
1366 llvm::PointerType* field_type =
1367 irb_.getJType(field_jty, kField)->getPointerTo();
1368
1369 llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
1370
1371 llvm::Value* field_addr =
1372 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1373
1374 // TODO: Check is_volatile. We need to generate atomic store instruction
1375 // when is_volatile is true.
1376 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
1377
1378 if (field_jty == kObject) { // If put an object, mark the GC card table.
1379 EmitMarkGCCard(new_value, object_addr);
1380 }
1381 }
1382
1383 return;
1384}
1385
TDYa127f71bf5a2012-07-29 20:09:52 -07001386llvm::Value* GBCExpanderPass::EmitLoadConstantClass(uint32_t dex_pc,
1387 uint32_t type_idx) {
1388 if (!compiler_->CanAccessTypeWithoutChecks(method_idx_, dex_cache_,
1389 *dex_file_, type_idx)) {
1390 llvm::Value* type_idx_value = irb_.getInt32(type_idx);
1391
1392 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1393
1394 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1395
1396 llvm::Function* runtime_func =
1397 irb_.GetRuntime(runtime_support::InitializeTypeAndVerifyAccess);
1398
1399 EmitUpdateDexPC(dex_pc);
1400
1401 llvm::Value* type_object_addr =
1402 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1403
1404 EmitGuard_ExceptionLandingPad(dex_pc);
1405
1406 return type_object_addr;
1407
1408 } else {
1409 // Try to load the class (type) object from the test cache.
1410 llvm::Value* type_field_addr =
1411 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
1412
1413 llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
1414
1415 if (compiler_->CanAssumeTypeIsPresentInDexCache(dex_cache_, type_idx)) {
1416 return type_object_addr;
1417 }
1418
1419 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1420
1421 // Test whether class (type) object is in the dex cache or not
1422 llvm::Value* equal_null =
1423 irb_.CreateICmpEQ(type_object_addr, irb_.getJNull());
1424
1425 llvm::BasicBlock* block_cont =
1426 CreateBasicBlockWithDexPC(dex_pc, "cont");
1427
1428 llvm::BasicBlock* block_load_class =
1429 CreateBasicBlockWithDexPC(dex_pc, "load_class");
1430
1431 irb_.CreateCondBr(equal_null, block_load_class, block_cont, kUnlikely);
1432
1433 // Failback routine to load the class object
1434 irb_.SetInsertPoint(block_load_class);
1435
1436 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeType);
1437
1438 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1439
1440 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1441
1442 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1443
1444 EmitUpdateDexPC(dex_pc);
1445
1446 llvm::Value* loaded_type_object_addr =
1447 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1448
1449 EmitGuard_ExceptionLandingPad(dex_pc);
1450
1451 llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
1452
1453 irb_.CreateBr(block_cont);
1454
1455 // Now the class object must be loaded
1456 irb_.SetInsertPoint(block_cont);
1457
1458 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1459
1460 phi->addIncoming(type_object_addr, block_original);
1461 phi->addIncoming(loaded_type_object_addr, block_after_load_class);
1462
1463 return phi;
1464 }
1465}
1466
TDYa1275a26d442012-07-26 18:58:38 -07001467llvm::Value* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc,
1468 uint32_t type_idx) {
1469 llvm::BasicBlock* block_load_static =
1470 CreateBasicBlockWithDexPC(dex_pc, "load_static");
1471
1472 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
1473
1474 // Load static storage from dex cache
1475 llvm::Value* storage_field_addr =
1476 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
1477
1478 llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
1479
1480 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1481
1482 // Test: Is the static storage of this class initialized?
1483 llvm::Value* equal_null =
1484 irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
1485
1486 irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely);
1487
1488 // Failback routine to load the class object
1489 irb_.SetInsertPoint(block_load_static);
1490
1491 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::InitializeStaticStorage);
1492
1493 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1494
1495 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1496
1497 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1498
1499 EmitUpdateDexPC(dex_pc);
1500
1501 llvm::Value* loaded_storage_object_addr =
1502 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1503
1504 EmitGuard_ExceptionLandingPad(dex_pc);
1505
1506 llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
1507
1508 irb_.CreateBr(block_cont);
1509
1510 // Now the class object must be loaded
1511 irb_.SetInsertPoint(block_cont);
1512
1513 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1514
1515 phi->addIncoming(storage_object_addr, block_original);
1516 phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
1517
1518 return phi;
1519}
1520
1521llvm::Value* GBCExpanderPass::Expand_HLSget(llvm::CallInst& call_inst,
1522 JType field_jty) {
1523 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1524
1525 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1526 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1527
1528 int field_offset;
1529 int ssb_index;
1530 bool is_referrers_class;
1531 bool is_volatile;
1532
1533 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
1534 field_idx, oat_compilation_unit_, field_offset, ssb_index,
1535 is_referrers_class, is_volatile, false);
1536
1537 llvm::Value* static_field_value;
1538
1539 if (!is_fast_path) {
1540 llvm::Function* runtime_func;
1541
1542 if (field_jty == kObject) {
1543 runtime_func = irb_.GetRuntime(runtime_support::GetObjectStatic);
1544 } else if (field_jty == kLong || field_jty == kDouble) {
1545 runtime_func = irb_.GetRuntime(runtime_support::Get64Static);
1546 } else {
1547 runtime_func = irb_.GetRuntime(runtime_support::Get32Static);
1548 }
1549
1550 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1551
1552 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1553
1554 EmitUpdateDexPC(dex_pc);
1555
1556 static_field_value =
1557 irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
1558
1559 EmitGuard_ExceptionLandingPad(dex_pc);
1560
1561 } else {
1562 DCHECK_GE(field_offset, 0);
1563
1564 llvm::Value* static_storage_addr = NULL;
1565
1566 if (is_referrers_class) {
1567 // Fast path, static storage base is this method's class
1568 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1569
1570 static_storage_addr =
1571 irb_.LoadFromObjectOffset(method_object_addr,
1572 Method::DeclaringClassOffset().Int32Value(),
1573 irb_.getJObjectTy(),
1574 kTBAAConstJObject);
1575 } else {
1576 // Medium path, static storage base in a different class which
1577 // requires checks that the other class is initialized
1578 DCHECK_GE(ssb_index, 0);
1579 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1580 }
1581
1582 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1583
1584 llvm::Value* static_field_addr =
1585 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
1586 irb_.getJType(field_jty, kField)->getPointerTo());
1587
1588 // TODO: Check is_volatile. We need to generate atomic load instruction
1589 // when is_volatile is true.
1590 static_field_value = irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
1591 }
1592
1593 if (field_jty == kFloat || field_jty == kDouble) {
1594 static_field_value =
1595 irb_.CreateBitCast(static_field_value, irb_.getJType(field_jty, kAccurate));
1596 }
1597
1598 return static_field_value;
1599}
1600
1601void GBCExpanderPass::Expand_HLSput(llvm::CallInst& call_inst,
1602 JType field_jty) {
1603 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1604
1605 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1606 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1607 llvm::Value* new_value = call_inst.getArgOperand(1);
1608
1609 if (field_jty == kFloat || field_jty == kDouble) {
1610 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty, kField));
1611 }
1612
1613 int field_offset;
1614 int ssb_index;
1615 bool is_referrers_class;
1616 bool is_volatile;
1617
1618 bool is_fast_path = compiler_->ComputeStaticFieldInfo(
1619 field_idx, oat_compilation_unit_, field_offset, ssb_index,
1620 is_referrers_class, is_volatile, true);
1621
1622 if (!is_fast_path) {
1623 llvm::Function* runtime_func;
1624
1625 if (field_jty == kObject) {
1626 runtime_func = irb_.GetRuntime(runtime_support::SetObjectStatic);
1627 } else if (field_jty == kLong || field_jty == kDouble) {
1628 runtime_func = irb_.GetRuntime(runtime_support::Set64Static);
1629 } else {
1630 runtime_func = irb_.GetRuntime(runtime_support::Set32Static);
1631 }
1632
1633 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1634
1635 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1636
1637 EmitUpdateDexPC(dex_pc);
1638
1639 irb_.CreateCall3(runtime_func, field_idx_value,
1640 method_object_addr, new_value);
1641
1642 EmitGuard_ExceptionLandingPad(dex_pc);
1643
1644 } else {
1645 DCHECK_GE(field_offset, 0);
1646
1647 llvm::Value* static_storage_addr = NULL;
1648
1649 if (is_referrers_class) {
1650 // Fast path, static storage base is this method's class
1651 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1652
1653 static_storage_addr =
1654 irb_.LoadFromObjectOffset(method_object_addr,
1655 Method::DeclaringClassOffset().Int32Value(),
1656 irb_.getJObjectTy(),
1657 kTBAAConstJObject);
1658 } else {
1659 // Medium path, static storage base in a different class which
1660 // requires checks that the other class is initialized
1661 DCHECK_GE(ssb_index, 0);
1662 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1663 }
1664
1665 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1666
1667 llvm::Value* static_field_addr =
1668 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
1669 irb_.getJType(field_jty, kField)->getPointerTo());
1670
1671 // TODO: Check is_volatile. We need to generate atomic store instruction
1672 // when is_volatile is true.
1673 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
1674
1675 if (field_jty == kObject) { // If put an object, mark the GC card table.
1676 EmitMarkGCCard(new_value, static_storage_addr);
1677 }
1678 }
1679
1680 return;
1681}
1682
TDYa127f71bf5a2012-07-29 20:09:52 -07001683llvm::Value* GBCExpanderPass::Expand_ConstString(llvm::CallInst& call_inst) {
1684 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1685
1686 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1687 uint32_t string_idx = LV2UInt(call_inst.getArgOperand(0));
1688
1689 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
1690
1691 llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
1692
1693 if (!compiler_->CanAssumeStringIsPresentInDexCache(dex_cache_, string_idx)) {
1694 llvm::BasicBlock* block_str_exist =
1695 CreateBasicBlockWithDexPC(dex_pc, "str_exist");
1696
1697 llvm::BasicBlock* block_str_resolve =
1698 CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
1699
1700 llvm::BasicBlock* block_cont =
1701 CreateBasicBlockWithDexPC(dex_pc, "str_cont");
1702
1703 // Test: Is the string resolved and in the dex cache?
1704 llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.getJNull());
1705
1706 irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist, kUnlikely);
1707
1708 // String is resolved, go to next basic block.
1709 irb_.SetInsertPoint(block_str_exist);
1710 irb_.CreateBr(block_cont);
1711
1712 // String is not resolved yet, resolve it now.
1713 irb_.SetInsertPoint(block_str_resolve);
1714
1715 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::ResolveString);
1716
1717 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1718
1719 llvm::Value* string_idx_value = irb_.getInt32(string_idx);
1720
1721 EmitUpdateDexPC(dex_pc);
1722
1723 llvm::Value* result = irb_.CreateCall2(runtime_func, method_object_addr,
1724 string_idx_value);
1725
1726 EmitGuard_ExceptionLandingPad(dex_pc);
1727
1728 llvm::BasicBlock* block_pre_cont = irb_.GetInsertBlock();
1729
1730 irb_.SetInsertPoint(block_cont);
1731
1732 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1733
1734 phi->addIncoming(string_addr, block_str_exist);
1735 phi->addIncoming(result, block_pre_cont);
1736
1737 string_addr = phi;
1738 }
1739
1740 return string_addr;
1741}
1742
1743llvm::Value* GBCExpanderPass::Expand_ConstClass(llvm::CallInst& call_inst) {
1744 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1745
1746 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) {
1755 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1756
1757 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1758 llvm::Value* object_addr = call_inst.getArgOperand(1);
1759
1760 // TODO: opt_flags
1761 EmitGuard_NullPointerException(dex_pc, object_addr);
1762
1763 irb_.Runtime().EmitLockObject(object_addr);
1764
1765 return;
1766}
1767
1768void GBCExpanderPass::Expand_MonitorExit(llvm::CallInst& call_inst) {
1769 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1770
1771 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1772 llvm::Value* object_addr = call_inst.getArgOperand(1);
1773
1774 // TODO: opt_flags
1775 EmitGuard_NullPointerException(dex_pc, object_addr);
1776
1777 EmitUpdateDexPC(dex_pc);
1778
1779 irb_.Runtime().EmitUnlockObject(object_addr);
1780
1781 EmitGuard_ExceptionLandingPad(dex_pc);
1782
1783 return;
1784}
1785
1786void GBCExpanderPass::Expand_HLCheckCast(llvm::CallInst& call_inst) {
1787 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1788
1789 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1790 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1791 llvm::Value* object_addr = call_inst.getArgOperand(1);
1792
1793 llvm::BasicBlock* block_test_class =
1794 CreateBasicBlockWithDexPC(dex_pc, "test_class");
1795
1796 llvm::BasicBlock* block_test_sub_class =
1797 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
1798
1799 llvm::BasicBlock* block_cont =
1800 CreateBasicBlockWithDexPC(dex_pc, "checkcast_cont");
1801
1802 // Test: Is the reference equal to null? Act as no-op when it is null.
1803 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
1804
1805 irb_.CreateCondBr(equal_null,
1806 block_cont,
1807 block_test_class);
1808
1809 // Test: Is the object instantiated from the given class?
1810 irb_.SetInsertPoint(block_test_class);
1811 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
1812 DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
1813
1814 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
1815
1816 llvm::Value* object_type_field_addr =
1817 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
1818
1819 llvm::Value* object_type_object_addr =
1820 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
1821
1822 llvm::Value* equal_class =
1823 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
1824
1825 irb_.CreateCondBr(equal_class,
1826 block_cont,
1827 block_test_sub_class);
1828
1829 // Test: Is the object instantiated from the subclass of the given class?
1830 irb_.SetInsertPoint(block_test_sub_class);
1831
1832 EmitUpdateDexPC(dex_pc);
1833
1834 irb_.CreateCall2(irb_.GetRuntime(runtime_support::CheckCast),
1835 type_object_addr, object_type_object_addr);
1836
1837 EmitGuard_ExceptionLandingPad(dex_pc);
1838
1839 irb_.CreateBr(block_cont);
1840
1841 irb_.SetInsertPoint(block_cont);
1842
1843 return;
1844}
1845
1846llvm::Value* GBCExpanderPass::Expand_InstanceOf(llvm::CallInst& call_inst) {
1847 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1848
1849 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1850 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1851 llvm::Value* object_addr = call_inst.getArgOperand(1);
1852
1853 llvm::BasicBlock* block_nullp =
1854 CreateBasicBlockWithDexPC(dex_pc, "nullp");
1855
1856 llvm::BasicBlock* block_test_class =
1857 CreateBasicBlockWithDexPC(dex_pc, "test_class");
1858
1859 llvm::BasicBlock* block_class_equals =
1860 CreateBasicBlockWithDexPC(dex_pc, "class_eq");
1861
1862 llvm::BasicBlock* block_test_sub_class =
1863 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
1864
1865 llvm::BasicBlock* block_cont =
1866 CreateBasicBlockWithDexPC(dex_pc, "instance_of_cont");
1867
1868 // Overview of the following code :
1869 // We check for null, if so, then false, otherwise check for class == . If so
1870 // then true, otherwise do callout slowpath.
1871 //
1872 // Test: Is the reference equal to null? Set 0 when it is null.
1873 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
1874
1875 irb_.CreateCondBr(equal_null, block_nullp, block_test_class);
1876
1877 irb_.SetInsertPoint(block_nullp);
1878 irb_.CreateBr(block_cont);
1879
1880 // Test: Is the object instantiated from the given class?
1881 irb_.SetInsertPoint(block_test_class);
1882 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
1883 DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
1884
1885 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
1886
1887 llvm::Value* object_type_field_addr =
1888 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
1889
1890 llvm::Value* object_type_object_addr =
1891 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
1892
1893 llvm::Value* equal_class =
1894 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
1895
1896 irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class);
1897
1898 irb_.SetInsertPoint(block_class_equals);
1899 irb_.CreateBr(block_cont);
1900
1901 // Test: Is the object instantiated from the subclass of the given class?
1902 irb_.SetInsertPoint(block_test_sub_class);
1903 llvm::Value* result =
1904 irb_.CreateCall2(irb_.GetRuntime(runtime_support::IsAssignable),
1905 type_object_addr, object_type_object_addr);
1906 irb_.CreateBr(block_cont);
1907
1908 irb_.SetInsertPoint(block_cont);
1909
1910 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJIntTy(), 3);
1911
1912 phi->addIncoming(irb_.getJInt(0), block_nullp);
1913 phi->addIncoming(irb_.getJInt(1), block_class_equals);
1914 phi->addIncoming(result, block_test_sub_class);
1915
1916 return phi;
1917}
1918
1919llvm::Value* GBCExpanderPass::Expand_NewInstance(llvm::CallInst& call_inst) {
1920 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1921
1922 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1923 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
1924
1925 llvm::Function* runtime_func;
1926 if (compiler_->CanAccessInstantiableTypeWithoutChecks(
1927 method_idx_, dex_cache_, *dex_file_, type_idx)) {
1928 runtime_func = irb_.GetRuntime(runtime_support::AllocObject);
1929 } else {
1930 runtime_func = irb_.GetRuntime(runtime_support::AllocObjectWithAccessCheck);
1931 }
1932
1933 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
1934
1935 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1936
1937 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1938
1939 EmitUpdateDexPC(dex_pc);
1940
1941 llvm::Value* object_addr =
1942 irb_.CreateCall3(runtime_func, type_index_value, method_object_addr, thread_object_addr);
1943
1944 EmitGuard_ExceptionLandingPad(dex_pc);
1945
1946 return object_addr;
1947}
1948
1949llvm::Value* GBCExpanderPass::Expand_HLInvoke(llvm::CallInst& call_inst) {
1950 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1951
1952 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1953 InvokeType invoke_type = static_cast<InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
1954 bool is_static = (invoke_type == kStatic);
1955 uint32_t callee_method_idx = LV2UInt(call_inst.getArgOperand(1));
1956
1957 // Compute invoke related information for compiler decision
1958 int vtable_idx = -1;
1959 uintptr_t direct_code = 0;
1960 uintptr_t direct_method = 0;
1961 bool is_fast_path = compiler_->
1962 ComputeInvokeInfo(callee_method_idx, oat_compilation_unit_,
1963 invoke_type, vtable_idx, direct_code, direct_method);
1964
1965 // Load *this* actual parameter
1966 llvm::Value* this_addr = NULL;
1967
1968 if (!is_static) {
1969 // Test: Is *this* parameter equal to null?
1970 this_addr = call_inst.getArgOperand(3);
1971 }
1972
1973 // Load the method object
1974 llvm::Value* callee_method_object_addr = NULL;
1975
1976 if (!is_fast_path) {
1977 callee_method_object_addr =
1978 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx, invoke_type,
1979 this_addr, dex_pc, is_fast_path);
1980
1981 // TODO: opt_flags
1982 if (!is_static) {
1983 EmitGuard_NullPointerException(dex_pc, this_addr);
1984 }
1985 } else {
1986 // TODO: opt_flags
1987 if (!is_static) {
1988 EmitGuard_NullPointerException(dex_pc, this_addr);
1989 }
1990
1991 switch (invoke_type) {
1992 case kStatic:
1993 case kDirect:
1994 if (direct_method != 0u &&
1995 direct_method != static_cast<uintptr_t>(-1)) {
1996 callee_method_object_addr =
1997 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_method),
1998 irb_.getJObjectTy());
1999 } else {
2000 callee_method_object_addr =
2001 EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
2002 }
2003 break;
2004
2005 case kVirtual:
2006 DCHECK(vtable_idx != -1);
2007 callee_method_object_addr =
2008 EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
2009 break;
2010
2011 case kSuper:
2012 LOG(FATAL) << "invoke-super should be promoted to invoke-direct in "
2013 "the fast path.";
2014 break;
2015
2016 case kInterface:
2017 callee_method_object_addr =
2018 EmitCallRuntimeForCalleeMethodObjectAddr(callee_method_idx,
2019 invoke_type, this_addr,
2020 dex_pc, is_fast_path);
2021 break;
2022 }
2023 }
2024
2025 // Load the actual parameter
2026 std::vector<llvm::Value*> args;
2027
2028 args.push_back(callee_method_object_addr); // method object for callee
2029
2030 for (uint32_t i = 3; i < call_inst.getNumArgOperands(); ++i) {
2031 args.push_back(call_inst.getArgOperand(i));
2032 }
2033
2034 llvm::Value* code_addr;
2035 if (direct_code != 0u &&
2036 direct_code != static_cast<uintptr_t>(-1)) {
2037 code_addr =
2038 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_code),
2039 GetFunctionType(callee_method_idx, is_static)->getPointerTo());
2040 } else {
2041 code_addr =
2042 irb_.LoadFromObjectOffset(callee_method_object_addr,
2043 Method::GetCodeOffset().Int32Value(),
2044 GetFunctionType(callee_method_idx, is_static)->getPointerTo(),
2045 kTBAAJRuntime);
2046 }
2047
2048 // Invoke callee
2049 EmitUpdateDexPC(dex_pc);
2050 llvm::Value* retval = irb_.CreateCall(code_addr, args);
2051 EmitGuard_ExceptionLandingPad(dex_pc);
2052
2053 return retval;
2054}
2055
2056llvm::Value* GBCExpanderPass::Expand_OptArrayLength(llvm::CallInst& call_inst) {
2057 ScopedExpandToBasicBlock eb(irb_, &call_inst);
2058
2059 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2060 // Get the array object address
2061 llvm::Value* array_addr = call_inst.getArgOperand(1);
2062
2063 // TODO: opt_flags
2064 EmitGuard_NullPointerException(dex_pc, array_addr);
2065
2066 // Get the array length and store it to the register
2067 return EmitLoadArrayLength(array_addr);
2068}
2069
2070llvm::Value* GBCExpanderPass::Expand_NewArray(llvm::CallInst& call_inst) {
2071 ScopedExpandToBasicBlock eb(irb_, &call_inst);
2072
2073 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2074 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2075 llvm::Value* length = call_inst.getArgOperand(1);
2076
2077 return EmitAllocNewArray(dex_pc, length, type_idx, false);
2078}
2079
2080llvm::Value* GBCExpanderPass::Expand_HLFilledNewArray(llvm::CallInst& call_inst) {
2081 ScopedExpandToBasicBlock eb(irb_, &call_inst);
2082
2083 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2084 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(1));
2085 uint32_t length = call_inst.getNumArgOperands() - 3;
2086
2087 llvm::Value* object_addr =
2088 EmitAllocNewArray(dex_pc, irb_.getInt32(length), type_idx, true);
2089
2090 if (length > 0) {
2091 // Check for the element type
2092 uint32_t type_desc_len = 0;
2093 const char* type_desc =
2094 dex_file_->StringByTypeIdx(type_idx, &type_desc_len);
2095
2096 DCHECK_GE(type_desc_len, 2u); // should be guaranteed by verifier
2097 DCHECK_EQ(type_desc[0], '['); // should be guaranteed by verifier
2098 bool is_elem_int_ty = (type_desc[1] == 'I');
2099
2100 uint32_t alignment;
2101 llvm::Constant* elem_size;
2102 llvm::PointerType* field_type;
2103
2104 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
2105 // as the element, thus we are only checking 2 cases: primitive int and
2106 // non-primitive type.
2107 if (is_elem_int_ty) {
2108 alignment = sizeof(int32_t);
2109 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
2110 field_type = irb_.getJIntTy()->getPointerTo();
2111 } else {
2112 alignment = irb_.getSizeOfPtrEquivInt();
2113 elem_size = irb_.getSizeOfPtrEquivIntValue();
2114 field_type = irb_.getJObjectTy()->getPointerTo();
2115 }
2116
2117 llvm::Value* data_field_offset =
2118 irb_.getPtrEquivInt(Array::DataOffset(alignment).Int32Value());
2119
2120 llvm::Value* data_field_addr =
2121 irb_.CreatePtrDisp(object_addr, data_field_offset, field_type);
2122
2123 // TODO: Tune this code. Currently we are generating one instruction for
2124 // one element which may be very space consuming. Maybe changing to use
2125 // memcpy may help; however, since we can't guarantee that the alloca of
2126 // dalvik register are continuous, we can't perform such optimization yet.
2127 for (uint32_t i = 0; i < length; ++i) {
2128 llvm::Value* reg_value = call_inst.getArgOperand(i+3);
2129
2130 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
2131
2132 data_field_addr =
2133 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
2134 }
2135 }
2136
2137 return object_addr;
2138}
2139
2140void GBCExpanderPass::Expand_HLFillArrayData(llvm::CallInst& call_inst) {
2141 ScopedExpandToBasicBlock eb(irb_, &call_inst);
2142
2143 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2144 int32_t payload_offset = static_cast<int32_t>(dex_pc) +
2145 LV2SInt(call_inst.getArgOperand(0));
2146 llvm::Value* array_addr = call_inst.getArgOperand(1);
2147
2148 const Instruction::ArrayDataPayload* payload =
2149 reinterpret_cast<const Instruction::ArrayDataPayload*>(
2150 code_item_->insns_ + payload_offset);
2151
2152 if (payload->element_count == 0) {
2153 // When the number of the elements in the payload is zero, we don't have
2154 // to copy any numbers. However, we should check whether the array object
2155 // address is equal to null or not.
2156 EmitGuard_NullPointerException(dex_pc, array_addr);
2157 } else {
2158 // To save the code size, we are going to call the runtime function to
2159 // copy the content from DexFile.
2160
2161 // NOTE: We will check for the NullPointerException in the runtime.
2162
2163 llvm::Function* runtime_func = irb_.GetRuntime(runtime_support::FillArrayData);
2164
2165 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2166
2167 EmitUpdateDexPC(dex_pc);
2168
2169 irb_.CreateCall4(runtime_func,
2170 method_object_addr, irb_.getInt32(dex_pc),
2171 array_addr, irb_.getInt32(payload_offset));
2172
2173 EmitGuard_ExceptionLandingPad(dex_pc);
2174 }
2175
2176 return;
2177}
2178
2179llvm::Value* GBCExpanderPass::EmitAllocNewArray(uint32_t dex_pc,
2180 llvm::Value* array_length_value,
2181 uint32_t type_idx,
2182 bool is_filled_new_array) {
2183 llvm::Function* runtime_func;
2184
2185 bool skip_access_check =
2186 compiler_->CanAccessTypeWithoutChecks(method_idx_, dex_cache_,
2187 *dex_file_, type_idx);
2188
2189
2190 if (is_filled_new_array) {
2191 runtime_func = skip_access_check ?
2192 irb_.GetRuntime(runtime_support::CheckAndAllocArray) :
2193 irb_.GetRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck);
2194 } else {
2195 runtime_func = skip_access_check ?
2196 irb_.GetRuntime(runtime_support::AllocArray) :
2197 irb_.GetRuntime(runtime_support::AllocArrayWithAccessCheck);
2198 }
2199
2200 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2201
2202 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2203
2204 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2205
2206 EmitUpdateDexPC(dex_pc);
2207
2208 llvm::Value* object_addr =
2209 irb_.CreateCall4(runtime_func, type_index_value, method_object_addr,
2210 array_length_value, thread_object_addr);
2211
2212 EmitGuard_ExceptionLandingPad(dex_pc);
2213
2214 return object_addr;
2215}
2216
2217llvm::Value* GBCExpanderPass::
2218EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
2219 InvokeType invoke_type,
2220 llvm::Value* this_addr,
2221 uint32_t dex_pc,
2222 bool is_fast_path) {
2223
2224 llvm::Function* runtime_func = NULL;
2225
2226 switch (invoke_type) {
2227 case kStatic:
2228 runtime_func = irb_.GetRuntime(runtime_support::FindStaticMethodWithAccessCheck);
2229 break;
2230
2231 case kDirect:
2232 runtime_func = irb_.GetRuntime(runtime_support::FindDirectMethodWithAccessCheck);
2233 break;
2234
2235 case kVirtual:
2236 runtime_func = irb_.GetRuntime(runtime_support::FindVirtualMethodWithAccessCheck);
2237 break;
2238
2239 case kSuper:
2240 runtime_func = irb_.GetRuntime(runtime_support::FindSuperMethodWithAccessCheck);
2241 break;
2242
2243 case kInterface:
2244 if (is_fast_path) {
2245 runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethod);
2246 } else {
2247 runtime_func = irb_.GetRuntime(runtime_support::FindInterfaceMethodWithAccessCheck);
2248 }
2249 break;
2250 }
2251
2252 llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
2253
2254 if (this_addr == NULL) {
2255 DCHECK_EQ(invoke_type, kStatic);
2256 this_addr = irb_.getJNull();
2257 }
2258
2259 llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
2260
2261 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2262
2263 EmitUpdateDexPC(dex_pc);
2264
2265 llvm::Value* callee_method_object_addr =
2266 irb_.CreateCall4(runtime_func,
2267 callee_method_idx_value,
2268 this_addr,
2269 caller_method_object_addr,
2270 thread_object_addr);
2271
2272 EmitGuard_ExceptionLandingPad(dex_pc);
2273
2274 return callee_method_object_addr;
2275}
2276
TDYa1275e869b62012-07-25 00:45:39 -07002277void GBCExpanderPass::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
2278 // Using runtime support, let the target can override by InlineAssembly.
2279 irb_.Runtime().EmitMarkGCCard(value, target_addr);
2280}
2281
2282void GBCExpanderPass::EmitUpdateDexPC(uint32_t dex_pc) {
2283 irb_.StoreToObjectOffset(shadow_frame_,
2284 ShadowFrame::DexPCOffset(),
2285 irb_.getInt32(dex_pc),
2286 kTBAAShadowFrame);
2287}
2288
2289void GBCExpanderPass::EmitGuard_DivZeroException(uint32_t dex_pc,
2290 llvm::Value* denominator,
2291 JType op_jty) {
2292 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
2293
2294 llvm::Constant* zero = irb_.getJZero(op_jty);
2295
2296 llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
2297
2298 llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
2299
2300 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
2301
2302 irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
2303
2304 irb_.SetInsertPoint(block_exception);
2305 EmitUpdateDexPC(dex_pc);
2306 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowDivZeroException));
2307 EmitBranchExceptionLandingPad(dex_pc);
2308
2309 irb_.SetInsertPoint(block_continue);
2310}
2311
2312void GBCExpanderPass::EmitGuard_NullPointerException(uint32_t dex_pc,
2313 llvm::Value* object) {
2314 llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
2315
2316 llvm::BasicBlock* block_exception =
2317 CreateBasicBlockWithDexPC(dex_pc, "nullp");
2318
2319 llvm::BasicBlock* block_continue =
2320 CreateBasicBlockWithDexPC(dex_pc, "cont");
2321
2322 irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
2323
2324 irb_.SetInsertPoint(block_exception);
2325 EmitUpdateDexPC(dex_pc);
2326 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowNullPointerException),
2327 irb_.getInt32(dex_pc));
2328 EmitBranchExceptionLandingPad(dex_pc);
2329
2330 irb_.SetInsertPoint(block_continue);
2331}
2332
2333void
2334GBCExpanderPass::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
2335 llvm::Value* array,
2336 llvm::Value* index) {
2337 llvm::Value* array_len = EmitLoadArrayLength(array);
2338
2339 llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
2340
2341 llvm::BasicBlock* block_exception =
2342 CreateBasicBlockWithDexPC(dex_pc, "overflow");
2343
2344 llvm::BasicBlock* block_continue =
2345 CreateBasicBlockWithDexPC(dex_pc, "cont");
2346
2347 irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
2348
2349 irb_.SetInsertPoint(block_exception);
2350
2351 EmitUpdateDexPC(dex_pc);
2352 irb_.CreateCall2(irb_.GetRuntime(runtime_support::ThrowIndexOutOfBounds), index, array_len);
2353 EmitBranchExceptionLandingPad(dex_pc);
2354
2355 irb_.SetInsertPoint(block_continue);
2356}
2357
2358void GBCExpanderPass::EmitGuard_ArrayException(uint32_t dex_pc,
2359 llvm::Value* array,
2360 llvm::Value* index) {
2361 EmitGuard_NullPointerException(dex_pc, array);
2362 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array, index);
2363}
2364
2365llvm::FunctionType* GBCExpanderPass::GetFunctionType(uint32_t method_idx,
2366 bool is_static) {
2367 // Get method signature
2368 DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
2369
2370 uint32_t shorty_size;
2371 const char* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
2372 CHECK_GE(shorty_size, 1u);
2373
2374 // Get return type
2375 llvm::Type* ret_type = irb_.getJType(shorty[0], kAccurate);
2376
2377 // Get argument type
2378 std::vector<llvm::Type*> args_type;
2379
2380 args_type.push_back(irb_.getJObjectTy()); // method object pointer
2381
2382 if (!is_static) {
2383 args_type.push_back(irb_.getJType('L', kAccurate)); // "this" object pointer
2384 }
2385
2386 for (uint32_t i = 1; i < shorty_size; ++i) {
TDYa127f71bf5a2012-07-29 20:09:52 -07002387#if defined(ART_USE_QUICK_COMPILER)
2388 char shorty_type = shorty[i];
2389 switch(shorty_type) {
2390 case 'Z' : shorty_type = 'I'; break;
2391 case 'B' : shorty_type = 'I'; break;
2392 case 'S' : shorty_type = 'I'; break;
2393 case 'C' : shorty_type = 'I'; break;
2394 default: break;
2395 }
2396 args_type.push_back(irb_.getJType(shorty_type, kAccurate));
2397#else
TDYa1275e869b62012-07-25 00:45:39 -07002398 args_type.push_back(irb_.getJType(shorty[i], kAccurate));
TDYa127f71bf5a2012-07-29 20:09:52 -07002399#endif
TDYa1275e869b62012-07-25 00:45:39 -07002400 }
2401
2402 return llvm::FunctionType::get(ret_type, args_type, false);
2403}
2404
2405
2406llvm::BasicBlock* GBCExpanderPass::
2407CreateBasicBlockWithDexPC(uint32_t dex_pc, const char* postfix) {
2408 std::string name;
2409
2410#if !defined(NDEBUG)
2411 StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
2412#endif
2413
2414 return llvm::BasicBlock::Create(context_, name, func_);
2415}
2416
2417llvm::BasicBlock* GBCExpanderPass::GetBasicBlock(uint32_t dex_pc) {
2418 DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
2419
2420 return basic_blocks_[dex_pc];
2421}
2422
2423int32_t GBCExpanderPass::GetTryItemOffset(uint32_t dex_pc) {
2424 int32_t min = 0;
2425 int32_t max = code_item_->tries_size_ - 1;
2426
2427 while (min <= max) {
2428 int32_t mid = min + (max - min) / 2;
2429
2430 const DexFile::TryItem* ti = DexFile::GetTryItems(*code_item_, mid);
2431 uint32_t start = ti->start_addr_;
2432 uint32_t end = start + ti->insn_count_;
2433
2434 if (dex_pc < start) {
2435 max = mid - 1;
2436 } else if (dex_pc >= end) {
2437 min = mid + 1;
2438 } else {
2439 return mid; // found
2440 }
2441 }
2442
2443 return -1; // not found
2444}
2445
2446llvm::BasicBlock* GBCExpanderPass::GetLandingPadBasicBlock(uint32_t dex_pc) {
2447 // Find the try item for this address in this method
2448 int32_t ti_offset = GetTryItemOffset(dex_pc);
2449
2450 if (ti_offset == -1) {
2451 return NULL; // No landing pad is available for this address.
2452 }
2453
2454 // Check for the existing landing pad basic block
2455 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2456 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
2457
2458 if (block_lpad) {
2459 // We have generated landing pad for this try item already. Return the
2460 // same basic block.
2461 return block_lpad;
2462 }
2463
2464 // Get try item from code item
2465 const DexFile::TryItem* ti = DexFile::GetTryItems(*code_item_, ti_offset);
2466
2467 std::string lpadname;
2468
2469#if !defined(NDEBUG)
2470 StringAppendF(&lpadname, "lpad%d_%04x_to_%04x", ti_offset, ti->start_addr_, ti->handler_off_);
2471#endif
2472
2473 // Create landing pad basic block
2474 block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
2475
2476 // Change IRBuilder insert point
2477 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2478 irb_.SetInsertPoint(block_lpad);
2479
2480 // Find catch block with matching type
2481 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2482
2483 llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
2484
2485 llvm::Value* catch_handler_index_value =
2486 irb_.CreateCall2(irb_.GetRuntime(runtime_support::FindCatchBlock),
2487 method_object_addr, ti_offset_value);
2488
2489 // Switch instruction (Go to unwind basic block by default)
2490 llvm::SwitchInst* sw =
2491 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
2492
2493 // Cases with matched catch block
2494 CatchHandlerIterator iter(*code_item_, ti->start_addr_);
2495
2496 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
2497 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
2498 }
2499
2500 // Restore the orignal insert point for IRBuilder
2501 irb_.restoreIP(irb_ip_original);
2502
2503 // Cache this landing pad
2504 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2505 basic_block_landing_pads_[ti_offset] = block_lpad;
2506
2507 return block_lpad;
2508}
2509
2510llvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() {
2511 // Check the existing unwinding baisc block block
2512 if (basic_block_unwind_ != NULL) {
2513 return basic_block_unwind_;
2514 }
2515
2516 // Create new basic block for unwinding
2517 basic_block_unwind_ =
2518 llvm::BasicBlock::Create(context_, "exception_unwind", func_);
2519
2520 // Change IRBuilder insert point
2521 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2522 irb_.SetInsertPoint(basic_block_unwind_);
2523
2524 // Pop the shadow frame
2525 Expand_PopShadowFrame();
2526
2527 // Emit the code to return default value (zero) for the given return type.
2528 char ret_shorty = oat_compilation_unit_->GetShorty()[0];
2529 if (ret_shorty == 'V') {
2530 irb_.CreateRetVoid();
2531 } else {
2532 irb_.CreateRet(irb_.getJZero(ret_shorty));
2533 }
2534
2535 // Restore the orignal insert point for IRBuilder
2536 irb_.restoreIP(irb_ip_original);
2537
2538 return basic_block_unwind_;
2539}
2540
2541void GBCExpanderPass::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
2542 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
2543 irb_.CreateBr(lpad);
2544 } else {
2545 irb_.CreateBr(GetUnwindBasicBlock());
2546 }
2547}
2548
2549void GBCExpanderPass::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
2550 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
2551
2552 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
2553
2554 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
2555 irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
2556 } else {
2557 irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
2558 }
2559
2560 irb_.SetInsertPoint(block_cont);
2561}
2562
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002563llvm::Value*
2564GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
2565 llvm::CallInst& call_inst) {
2566 switch (intr_id) {
2567 //==- Thread -----------------------------------------------------------==//
2568 case IntrinsicHelper::GetCurrentThread: {
TDYa127b672d1e2012-06-28 21:21:45 -07002569 return irb_.Runtime().EmitGetCurrentThread();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002570 }
Logan Chiend54a23d2012-07-24 11:19:23 -07002571 case IntrinsicHelper::TestSuspend:
Logan Chien75e4b602012-07-23 14:24:12 -07002572 case IntrinsicHelper::CheckSuspend: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002573 Expand_TestSuspend(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002574 return NULL;
2575 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002576 case IntrinsicHelper::MarkGCCard: {
TDYa1279a129452012-07-19 03:10:08 -07002577 Expand_MarkGCCard(call_inst);
2578 return NULL;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002579 }
Logan Chien75e4b602012-07-23 14:24:12 -07002580
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002581 //==- Exception --------------------------------------------------------==//
2582 case IntrinsicHelper::ThrowException: {
2583 return ExpandToRuntime(runtime_support::ThrowException, call_inst);
2584 }
TDYa127f71bf5a2012-07-29 20:09:52 -07002585 case IntrinsicHelper::HLThrowException: {
2586 ScopedExpandToBasicBlock eb(irb_, &call_inst);
2587
2588 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2589
2590 EmitUpdateDexPC(dex_pc);
2591
2592 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowException),
2593 call_inst.getArgOperand(0));
2594
2595 EmitGuard_ExceptionLandingPad(dex_pc);
2596 return NULL;
2597 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002598 case IntrinsicHelper::GetException: {
2599 return Expand_GetException();
2600 }
2601 case IntrinsicHelper::IsExceptionPending: {
2602 return irb_.Runtime().EmitIsExceptionPending();
2603 }
2604 case IntrinsicHelper::FindCatchBlock: {
2605 return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
2606 }
2607 case IntrinsicHelper::ThrowDivZeroException: {
2608 return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
2609 }
2610 case IntrinsicHelper::ThrowNullPointerException: {
2611 return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
2612 }
2613 case IntrinsicHelper::ThrowIndexOutOfBounds: {
2614 return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
2615 }
Logan Chien75e4b602012-07-23 14:24:12 -07002616
2617 //==- Const String -----------------------------------------------------==//
2618 case IntrinsicHelper::ConstString: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002619 return Expand_ConstString(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002620 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002621 case IntrinsicHelper::LoadStringFromDexCache: {
2622 return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
2623 }
2624 case IntrinsicHelper::ResolveString: {
2625 return ExpandToRuntime(runtime_support::ResolveString, call_inst);
2626 }
Logan Chien75e4b602012-07-23 14:24:12 -07002627
2628 //==- Const Class ------------------------------------------------------==//
2629 case IntrinsicHelper::ConstClass: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002630 return Expand_ConstClass(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002631 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002632 case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
2633 return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
2634 }
2635 case IntrinsicHelper::LoadTypeFromDexCache: {
2636 return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
2637 }
2638 case IntrinsicHelper::InitializeType: {
2639 return ExpandToRuntime(runtime_support::InitializeType, call_inst);
2640 }
Logan Chien75e4b602012-07-23 14:24:12 -07002641
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002642 //==- Lock -------------------------------------------------------------==//
2643 case IntrinsicHelper::LockObject: {
2644 Expand_LockObject(call_inst.getArgOperand(0));
2645 return NULL;
2646 }
2647 case IntrinsicHelper::UnlockObject: {
2648 Expand_UnlockObject(call_inst.getArgOperand(0));
2649 return NULL;
2650 }
Logan Chien75e4b602012-07-23 14:24:12 -07002651
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002652 //==- Cast -------------------------------------------------------------==//
2653 case IntrinsicHelper::CheckCast: {
2654 return ExpandToRuntime(runtime_support::CheckCast, call_inst);
2655 }
Logan Chien75e4b602012-07-23 14:24:12 -07002656 case IntrinsicHelper::HLCheckCast: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002657 Expand_HLCheckCast(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002658 return NULL;
2659 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002660 case IntrinsicHelper::IsAssignable: {
2661 return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
2662 }
Logan Chien75e4b602012-07-23 14:24:12 -07002663
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002664 //==- Alloc ------------------------------------------------------------==//
2665 case IntrinsicHelper::AllocObject: {
2666 return ExpandToRuntime(runtime_support::AllocObject, call_inst);
2667 }
2668 case IntrinsicHelper::AllocObjectWithAccessCheck: {
2669 return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
2670 }
Logan Chien75e4b602012-07-23 14:24:12 -07002671
2672 //==- Instance ---------------------------------------------------------==//
2673 case IntrinsicHelper::NewInstance: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002674 return Expand_NewInstance(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002675 }
2676 case IntrinsicHelper::InstanceOf: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002677 return Expand_InstanceOf(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002678 }
2679
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002680 //==- Array ------------------------------------------------------------==//
Logan Chien75e4b602012-07-23 14:24:12 -07002681 case IntrinsicHelper::NewArray: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002682 return Expand_NewArray(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002683 }
2684 case IntrinsicHelper::OptArrayLength: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002685 return Expand_OptArrayLength(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002686 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002687 case IntrinsicHelper::ArrayLength: {
2688 return EmitLoadArrayLength(call_inst.getArgOperand(0));
2689 }
2690 case IntrinsicHelper::AllocArray: {
2691 return ExpandToRuntime(runtime_support::AllocArray, call_inst);
2692 }
2693 case IntrinsicHelper::AllocArrayWithAccessCheck: {
2694 return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
2695 call_inst);
2696 }
2697 case IntrinsicHelper::CheckAndAllocArray: {
2698 return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
2699 }
2700 case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
2701 return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
2702 call_inst);
2703 }
2704 case IntrinsicHelper::ArrayGet: {
2705 return Expand_ArrayGet(call_inst.getArgOperand(0),
2706 call_inst.getArgOperand(1),
2707 kInt);
2708 }
2709 case IntrinsicHelper::ArrayGetWide: {
2710 return Expand_ArrayGet(call_inst.getArgOperand(0),
2711 call_inst.getArgOperand(1),
2712 kLong);
2713 }
2714 case IntrinsicHelper::ArrayGetObject: {
2715 return Expand_ArrayGet(call_inst.getArgOperand(0),
2716 call_inst.getArgOperand(1),
2717 kObject);
2718 }
2719 case IntrinsicHelper::ArrayGetBoolean: {
2720 return Expand_ArrayGet(call_inst.getArgOperand(0),
2721 call_inst.getArgOperand(1),
2722 kBoolean);
2723 }
2724 case IntrinsicHelper::ArrayGetByte: {
2725 return Expand_ArrayGet(call_inst.getArgOperand(0),
2726 call_inst.getArgOperand(1),
2727 kByte);
2728 }
2729 case IntrinsicHelper::ArrayGetChar: {
2730 return Expand_ArrayGet(call_inst.getArgOperand(0),
2731 call_inst.getArgOperand(1),
2732 kChar);
2733 }
2734 case IntrinsicHelper::ArrayGetShort: {
2735 return Expand_ArrayGet(call_inst.getArgOperand(0),
2736 call_inst.getArgOperand(1),
2737 kShort);
2738 }
2739 case IntrinsicHelper::ArrayPut: {
2740 Expand_ArrayPut(call_inst.getArgOperand(0),
2741 call_inst.getArgOperand(1),
2742 call_inst.getArgOperand(2),
2743 kInt);
2744 return NULL;
2745 }
2746 case IntrinsicHelper::ArrayPutWide: {
2747 Expand_ArrayPut(call_inst.getArgOperand(0),
2748 call_inst.getArgOperand(1),
2749 call_inst.getArgOperand(2),
2750 kLong);
2751 return NULL;
2752 }
2753 case IntrinsicHelper::ArrayPutObject: {
2754 Expand_ArrayPut(call_inst.getArgOperand(0),
2755 call_inst.getArgOperand(1),
2756 call_inst.getArgOperand(2),
2757 kObject);
2758 return NULL;
2759 }
2760 case IntrinsicHelper::ArrayPutBoolean: {
2761 Expand_ArrayPut(call_inst.getArgOperand(0),
2762 call_inst.getArgOperand(1),
2763 call_inst.getArgOperand(2),
2764 kBoolean);
2765 return NULL;
2766 }
2767 case IntrinsicHelper::ArrayPutByte: {
2768 Expand_ArrayPut(call_inst.getArgOperand(0),
2769 call_inst.getArgOperand(1),
2770 call_inst.getArgOperand(2),
2771 kByte);
2772 return NULL;
2773 }
2774 case IntrinsicHelper::ArrayPutChar: {
2775 Expand_ArrayPut(call_inst.getArgOperand(0),
2776 call_inst.getArgOperand(1),
2777 call_inst.getArgOperand(2),
2778 kChar);
2779 return NULL;
2780 }
2781 case IntrinsicHelper::ArrayPutShort: {
2782 Expand_ArrayPut(call_inst.getArgOperand(0),
2783 call_inst.getArgOperand(1),
2784 call_inst.getArgOperand(2),
2785 kShort);
2786 return NULL;
2787 }
2788 case IntrinsicHelper::CheckPutArrayElement: {
2789 return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
2790 }
2791 case IntrinsicHelper::FilledNewArray: {
2792 Expand_FilledNewArray(call_inst);
2793 return NULL;
2794 }
2795 case IntrinsicHelper::FillArrayData: {
2796 return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
2797 }
Logan Chien75e4b602012-07-23 14:24:12 -07002798 case IntrinsicHelper::HLFillArrayData: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002799 Expand_HLFillArrayData(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002800 return NULL;
2801 }
2802 case IntrinsicHelper::HLFilledNewArray: {
TDYa127f71bf5a2012-07-29 20:09:52 -07002803 return Expand_HLFilledNewArray(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07002804 }
2805
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002806 //==- Instance Field ---------------------------------------------------==//
2807 case IntrinsicHelper::InstanceFieldGet:
2808 case IntrinsicHelper::InstanceFieldGetBoolean:
2809 case IntrinsicHelper::InstanceFieldGetByte:
2810 case IntrinsicHelper::InstanceFieldGetChar:
2811 case IntrinsicHelper::InstanceFieldGetShort: {
2812 return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
2813 }
2814 case IntrinsicHelper::InstanceFieldGetWide: {
2815 return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
2816 }
2817 case IntrinsicHelper::InstanceFieldGetObject: {
2818 return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
2819 }
2820 case IntrinsicHelper::InstanceFieldGetFast: {
2821 return Expand_IGetFast(call_inst.getArgOperand(0),
2822 call_inst.getArgOperand(1),
2823 call_inst.getArgOperand(2),
2824 kInt);
2825 }
2826 case IntrinsicHelper::InstanceFieldGetWideFast: {
2827 return Expand_IGetFast(call_inst.getArgOperand(0),
2828 call_inst.getArgOperand(1),
2829 call_inst.getArgOperand(2),
2830 kLong);
2831 }
2832 case IntrinsicHelper::InstanceFieldGetObjectFast: {
2833 return Expand_IGetFast(call_inst.getArgOperand(0),
2834 call_inst.getArgOperand(1),
2835 call_inst.getArgOperand(2),
2836 kObject);
2837 }
2838 case IntrinsicHelper::InstanceFieldGetBooleanFast: {
2839 return Expand_IGetFast(call_inst.getArgOperand(0),
2840 call_inst.getArgOperand(1),
2841 call_inst.getArgOperand(2),
2842 kBoolean);
2843 }
2844 case IntrinsicHelper::InstanceFieldGetByteFast: {
2845 return Expand_IGetFast(call_inst.getArgOperand(0),
2846 call_inst.getArgOperand(1),
2847 call_inst.getArgOperand(2),
2848 kByte);
2849 }
2850 case IntrinsicHelper::InstanceFieldGetCharFast: {
2851 return Expand_IGetFast(call_inst.getArgOperand(0),
2852 call_inst.getArgOperand(1),
2853 call_inst.getArgOperand(2),
2854 kChar);
2855 }
2856 case IntrinsicHelper::InstanceFieldGetShortFast: {
2857 return Expand_IGetFast(call_inst.getArgOperand(0),
2858 call_inst.getArgOperand(1),
2859 call_inst.getArgOperand(2),
2860 kShort);
2861 }
2862 case IntrinsicHelper::InstanceFieldPut:
2863 case IntrinsicHelper::InstanceFieldPutBoolean:
2864 case IntrinsicHelper::InstanceFieldPutByte:
2865 case IntrinsicHelper::InstanceFieldPutChar:
2866 case IntrinsicHelper::InstanceFieldPutShort: {
2867 return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
2868 }
2869 case IntrinsicHelper::InstanceFieldPutWide: {
2870 return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
2871 }
2872 case IntrinsicHelper::InstanceFieldPutObject: {
2873 return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
2874 }
2875 case IntrinsicHelper::InstanceFieldPutFast: {
2876 Expand_IPutFast(call_inst.getArgOperand(0),
2877 call_inst.getArgOperand(1),
2878 call_inst.getArgOperand(2),
2879 call_inst.getArgOperand(3),
2880 kInt);
2881 return NULL;
2882 }
2883 case IntrinsicHelper::InstanceFieldPutWideFast: {
2884 Expand_IPutFast(call_inst.getArgOperand(0),
2885 call_inst.getArgOperand(1),
2886 call_inst.getArgOperand(2),
2887 call_inst.getArgOperand(3),
2888 kLong);
2889 return NULL;
2890 }
2891 case IntrinsicHelper::InstanceFieldPutObjectFast: {
2892 Expand_IPutFast(call_inst.getArgOperand(0),
2893 call_inst.getArgOperand(1),
2894 call_inst.getArgOperand(2),
2895 call_inst.getArgOperand(3),
2896 kObject);
2897 return NULL;
2898 }
2899 case IntrinsicHelper::InstanceFieldPutBooleanFast: {
2900 Expand_IPutFast(call_inst.getArgOperand(0),
2901 call_inst.getArgOperand(1),
2902 call_inst.getArgOperand(2),
2903 call_inst.getArgOperand(3),
2904 kBoolean);
2905 return NULL;
2906 }
2907 case IntrinsicHelper::InstanceFieldPutByteFast: {
2908 Expand_IPutFast(call_inst.getArgOperand(0),
2909 call_inst.getArgOperand(1),
2910 call_inst.getArgOperand(2),
2911 call_inst.getArgOperand(3),
2912 kByte);
2913 return NULL;
2914 }
2915 case IntrinsicHelper::InstanceFieldPutCharFast: {
2916 Expand_IPutFast(call_inst.getArgOperand(0),
2917 call_inst.getArgOperand(1),
2918 call_inst.getArgOperand(2),
2919 call_inst.getArgOperand(3),
2920 kChar);
2921 return NULL;
2922 }
2923 case IntrinsicHelper::InstanceFieldPutShortFast: {
2924 Expand_IPutFast(call_inst.getArgOperand(0),
2925 call_inst.getArgOperand(1),
2926 call_inst.getArgOperand(2),
2927 call_inst.getArgOperand(3),
2928 kShort);
2929 return NULL;
2930 }
Logan Chien75e4b602012-07-23 14:24:12 -07002931
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002932 //==- Static Field -----------------------------------------------------==//
2933 case IntrinsicHelper::StaticFieldGet:
2934 case IntrinsicHelper::StaticFieldGetBoolean:
2935 case IntrinsicHelper::StaticFieldGetByte:
2936 case IntrinsicHelper::StaticFieldGetChar:
2937 case IntrinsicHelper::StaticFieldGetShort: {
2938 return ExpandToRuntime(runtime_support::Get32Static, call_inst);
2939 }
2940 case IntrinsicHelper::StaticFieldGetWide: {
2941 return ExpandToRuntime(runtime_support::Get64Static, call_inst);
2942 }
2943 case IntrinsicHelper::StaticFieldGetObject: {
2944 return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
2945 }
2946 case IntrinsicHelper::StaticFieldGetFast: {
2947 return Expand_SGetFast(call_inst.getArgOperand(0),
2948 call_inst.getArgOperand(1),
2949 call_inst.getArgOperand(2),
2950 kInt);
2951 }
2952 case IntrinsicHelper::StaticFieldGetWideFast: {
2953 return Expand_SGetFast(call_inst.getArgOperand(0),
2954 call_inst.getArgOperand(1),
2955 call_inst.getArgOperand(2),
2956 kLong);
2957 }
2958 case IntrinsicHelper::StaticFieldGetObjectFast: {
2959 return Expand_SGetFast(call_inst.getArgOperand(0),
2960 call_inst.getArgOperand(1),
2961 call_inst.getArgOperand(2),
2962 kObject);
2963 }
2964 case IntrinsicHelper::StaticFieldGetBooleanFast: {
2965 return Expand_SGetFast(call_inst.getArgOperand(0),
2966 call_inst.getArgOperand(1),
2967 call_inst.getArgOperand(2),
2968 kBoolean);
2969 }
2970 case IntrinsicHelper::StaticFieldGetByteFast: {
2971 return Expand_SGetFast(call_inst.getArgOperand(0),
2972 call_inst.getArgOperand(1),
2973 call_inst.getArgOperand(2),
2974 kByte);
2975 }
2976 case IntrinsicHelper::StaticFieldGetCharFast: {
2977 return Expand_SGetFast(call_inst.getArgOperand(0),
2978 call_inst.getArgOperand(1),
2979 call_inst.getArgOperand(2),
2980 kChar);
2981 }
2982 case IntrinsicHelper::StaticFieldGetShortFast: {
2983 return Expand_SGetFast(call_inst.getArgOperand(0),
2984 call_inst.getArgOperand(1),
2985 call_inst.getArgOperand(2),
2986 kShort);
2987 }
2988 case IntrinsicHelper::StaticFieldPut:
2989 case IntrinsicHelper::StaticFieldPutBoolean:
2990 case IntrinsicHelper::StaticFieldPutByte:
2991 case IntrinsicHelper::StaticFieldPutChar:
2992 case IntrinsicHelper::StaticFieldPutShort: {
2993 return ExpandToRuntime(runtime_support::Set32Static, call_inst);
2994 }
2995 case IntrinsicHelper::StaticFieldPutWide: {
2996 return ExpandToRuntime(runtime_support::Set64Static, call_inst);
2997 }
2998 case IntrinsicHelper::StaticFieldPutObject: {
2999 return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
3000 }
3001 case IntrinsicHelper::StaticFieldPutFast: {
3002 Expand_SPutFast(call_inst.getArgOperand(0),
3003 call_inst.getArgOperand(1),
3004 call_inst.getArgOperand(2),
3005 call_inst.getArgOperand(3),
3006 kInt);
3007 return NULL;
3008 }
3009 case IntrinsicHelper::StaticFieldPutWideFast: {
3010 Expand_SPutFast(call_inst.getArgOperand(0),
3011 call_inst.getArgOperand(1),
3012 call_inst.getArgOperand(2),
3013 call_inst.getArgOperand(3),
3014 kLong);
3015 return NULL;
3016 }
3017 case IntrinsicHelper::StaticFieldPutObjectFast: {
3018 Expand_SPutFast(call_inst.getArgOperand(0),
3019 call_inst.getArgOperand(1),
3020 call_inst.getArgOperand(2),
3021 call_inst.getArgOperand(3),
3022 kObject);
3023 return NULL;
3024 }
3025 case IntrinsicHelper::StaticFieldPutBooleanFast: {
3026 Expand_SPutFast(call_inst.getArgOperand(0),
3027 call_inst.getArgOperand(1),
3028 call_inst.getArgOperand(2),
3029 call_inst.getArgOperand(3),
3030 kBoolean);
3031 return NULL;
3032 }
3033 case IntrinsicHelper::StaticFieldPutByteFast: {
3034 Expand_SPutFast(call_inst.getArgOperand(0),
3035 call_inst.getArgOperand(1),
3036 call_inst.getArgOperand(2),
3037 call_inst.getArgOperand(3),
3038 kByte);
3039 return NULL;
3040 }
3041 case IntrinsicHelper::StaticFieldPutCharFast: {
3042 Expand_SPutFast(call_inst.getArgOperand(0),
3043 call_inst.getArgOperand(1),
3044 call_inst.getArgOperand(2),
3045 call_inst.getArgOperand(3),
3046 kChar);
3047 return NULL;
3048 }
3049 case IntrinsicHelper::StaticFieldPutShortFast: {
3050 Expand_SPutFast(call_inst.getArgOperand(0),
3051 call_inst.getArgOperand(1),
3052 call_inst.getArgOperand(2),
3053 call_inst.getArgOperand(3),
3054 kShort);
3055 return NULL;
3056 }
3057 case IntrinsicHelper::LoadDeclaringClassSSB: {
3058 return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
3059 }
3060 case IntrinsicHelper::LoadClassSSBFromDexCache: {
3061 return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
3062 }
3063 case IntrinsicHelper::InitializeAndLoadClassSSB: {
3064 return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
3065 }
Logan Chien75e4b602012-07-23 14:24:12 -07003066
3067 //==- High-level Array -------------------------------------------------==//
3068 case IntrinsicHelper::HLArrayGet: {
TDYa1275a26d442012-07-26 18:58:38 -07003069 return Expand_HLArrayGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003070 }
3071 case IntrinsicHelper::HLArrayGetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003072 return Expand_HLArrayGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003073 }
3074 case IntrinsicHelper::HLArrayGetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003075 return Expand_HLArrayGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003076 }
3077 case IntrinsicHelper::HLArrayGetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003078 return Expand_HLArrayGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003079 }
3080 case IntrinsicHelper::HLArrayGetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003081 return Expand_HLArrayGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003082 }
3083 case IntrinsicHelper::HLArrayGetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003084 return Expand_HLArrayGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003085 }
3086 case IntrinsicHelper::HLArrayGetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003087 return Expand_HLArrayGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003088 }
3089 case IntrinsicHelper::HLArrayGetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003090 return Expand_HLArrayGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003091 }
3092 case IntrinsicHelper::HLArrayGetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003093 return Expand_HLArrayGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003094 }
3095 case IntrinsicHelper::HLArrayPut: {
TDYa1275a26d442012-07-26 18:58:38 -07003096 Expand_HLArrayPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003097 return NULL;
3098 }
3099 case IntrinsicHelper::HLArrayPutBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003100 Expand_HLArrayPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003101 return NULL;
3102 }
3103 case IntrinsicHelper::HLArrayPutByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003104 Expand_HLArrayPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003105 return NULL;
3106 }
3107 case IntrinsicHelper::HLArrayPutChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003108 Expand_HLArrayPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003109 return NULL;
3110 }
3111 case IntrinsicHelper::HLArrayPutShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003112 Expand_HLArrayPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003113 return NULL;
3114 }
3115 case IntrinsicHelper::HLArrayPutFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003116 Expand_HLArrayPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003117 return NULL;
3118 }
3119 case IntrinsicHelper::HLArrayPutWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003120 Expand_HLArrayPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003121 return NULL;
3122 }
3123 case IntrinsicHelper::HLArrayPutDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003124 Expand_HLArrayPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003125 return NULL;
3126 }
3127 case IntrinsicHelper::HLArrayPutObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003128 Expand_HLArrayPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003129 return NULL;
3130 }
3131
3132 //==- High-level Instance ----------------------------------------------==//
3133 case IntrinsicHelper::HLIGet: {
TDYa1275e869b62012-07-25 00:45:39 -07003134 return Expand_HLIGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003135 }
3136 case IntrinsicHelper::HLIGetBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07003137 return Expand_HLIGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003138 }
3139 case IntrinsicHelper::HLIGetByte: {
TDYa1275e869b62012-07-25 00:45:39 -07003140 return Expand_HLIGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003141 }
3142 case IntrinsicHelper::HLIGetChar: {
TDYa1275e869b62012-07-25 00:45:39 -07003143 return Expand_HLIGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003144 }
3145 case IntrinsicHelper::HLIGetShort: {
TDYa1275e869b62012-07-25 00:45:39 -07003146 return Expand_HLIGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003147 }
3148 case IntrinsicHelper::HLIGetFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07003149 return Expand_HLIGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003150 }
3151 case IntrinsicHelper::HLIGetWide: {
TDYa1275e869b62012-07-25 00:45:39 -07003152 return Expand_HLIGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003153 }
3154 case IntrinsicHelper::HLIGetDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07003155 return Expand_HLIGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003156 }
3157 case IntrinsicHelper::HLIGetObject: {
TDYa1275e869b62012-07-25 00:45:39 -07003158 return Expand_HLIGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003159 }
3160 case IntrinsicHelper::HLIPut: {
TDYa1275e869b62012-07-25 00:45:39 -07003161 Expand_HLIPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003162 return NULL;
3163 }
3164 case IntrinsicHelper::HLIPutBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07003165 Expand_HLIPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003166 return NULL;
3167 }
3168 case IntrinsicHelper::HLIPutByte: {
TDYa1275e869b62012-07-25 00:45:39 -07003169 Expand_HLIPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003170 return NULL;
3171 }
3172 case IntrinsicHelper::HLIPutChar: {
TDYa1275e869b62012-07-25 00:45:39 -07003173 Expand_HLIPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003174 return NULL;
3175 }
3176 case IntrinsicHelper::HLIPutShort: {
TDYa1275e869b62012-07-25 00:45:39 -07003177 Expand_HLIPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003178 return NULL;
3179 }
3180 case IntrinsicHelper::HLIPutFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07003181 Expand_HLIPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003182 return NULL;
3183 }
3184 case IntrinsicHelper::HLIPutWide: {
TDYa1275e869b62012-07-25 00:45:39 -07003185 Expand_HLIPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003186 return NULL;
3187 }
3188 case IntrinsicHelper::HLIPutDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07003189 Expand_HLIPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003190 return NULL;
3191 }
3192 case IntrinsicHelper::HLIPutObject: {
TDYa1275e869b62012-07-25 00:45:39 -07003193 Expand_HLIPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003194 return NULL;
3195 }
3196
3197 //==- High-level Invoke ------------------------------------------------==//
TDYa127f71bf5a2012-07-29 20:09:52 -07003198 case IntrinsicHelper::HLInvokeVoid:
3199 case IntrinsicHelper::HLInvokeObj:
3200 case IntrinsicHelper::HLInvokeInt:
3201 case IntrinsicHelper::HLInvokeFloat:
3202 case IntrinsicHelper::HLInvokeLong:
Logan Chien75e4b602012-07-23 14:24:12 -07003203 case IntrinsicHelper::HLInvokeDouble: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003204 return Expand_HLInvoke(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003205 }
3206
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003207 //==- Invoke -----------------------------------------------------------==//
3208 case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
3209 return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
3210 }
3211 case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
3212 return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
3213 }
3214 case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
3215 return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
3216 }
3217 case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
3218 return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
3219 }
3220 case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
3221 return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
3222 }
3223 case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
3224 return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
3225 }
3226 case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
3227 return Expand_GetVirtualCalleeMethodObjAddrFast(
3228 call_inst.getArgOperand(0), call_inst.getArgOperand(1));
3229 }
3230 case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
3231 return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
3232 }
3233 case IntrinsicHelper::InvokeRetVoid:
3234 case IntrinsicHelper::InvokeRetBoolean:
3235 case IntrinsicHelper::InvokeRetByte:
3236 case IntrinsicHelper::InvokeRetChar:
3237 case IntrinsicHelper::InvokeRetShort:
3238 case IntrinsicHelper::InvokeRetInt:
3239 case IntrinsicHelper::InvokeRetLong:
3240 case IntrinsicHelper::InvokeRetFloat:
3241 case IntrinsicHelper::InvokeRetDouble:
3242 case IntrinsicHelper::InvokeRetObject: {
3243 return Expand_Invoke(call_inst);
3244 }
Logan Chien75e4b602012-07-23 14:24:12 -07003245
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003246 //==- Math -------------------------------------------------------------==//
3247 case IntrinsicHelper::DivInt: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003248 return Expand_DivRem(call_inst, /* is_div */true, kInt);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003249 }
3250 case IntrinsicHelper::RemInt: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003251 return Expand_DivRem(call_inst, /* is_div */false, kInt);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003252 }
3253 case IntrinsicHelper::DivLong: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003254 return Expand_DivRem(call_inst, /* is_div */true, kLong);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003255 }
3256 case IntrinsicHelper::RemLong: {
TDYa1274ec8ccd2012-08-11 07:04:57 -07003257 return Expand_DivRem(call_inst, /* is_div */false, kLong);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003258 }
3259 case IntrinsicHelper::D2L: {
3260 return ExpandToRuntime(runtime_support::art_d2l, call_inst);
3261 }
3262 case IntrinsicHelper::D2I: {
3263 return ExpandToRuntime(runtime_support::art_d2i, call_inst);
3264 }
3265 case IntrinsicHelper::F2L: {
3266 return ExpandToRuntime(runtime_support::art_f2l, call_inst);
3267 }
3268 case IntrinsicHelper::F2I: {
3269 return ExpandToRuntime(runtime_support::art_f2i, call_inst);
3270 }
Logan Chien75e4b602012-07-23 14:24:12 -07003271
3272 //==- High-level Static ------------------------------------------------==//
3273 case IntrinsicHelper::HLSget: {
TDYa1275a26d442012-07-26 18:58:38 -07003274 return Expand_HLSget(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003275 }
3276 case IntrinsicHelper::HLSgetBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003277 return Expand_HLSget(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003278 }
3279 case IntrinsicHelper::HLSgetByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003280 return Expand_HLSget(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003281 }
3282 case IntrinsicHelper::HLSgetChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003283 return Expand_HLSget(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003284 }
3285 case IntrinsicHelper::HLSgetShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003286 return Expand_HLSget(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003287 }
3288 case IntrinsicHelper::HLSgetFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003289 return Expand_HLSget(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003290 }
3291 case IntrinsicHelper::HLSgetWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003292 return Expand_HLSget(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003293 }
3294 case IntrinsicHelper::HLSgetDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003295 return Expand_HLSget(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003296 }
3297 case IntrinsicHelper::HLSgetObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003298 return Expand_HLSget(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003299 }
3300 case IntrinsicHelper::HLSput: {
TDYa1275a26d442012-07-26 18:58:38 -07003301 Expand_HLSput(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07003302 return NULL;
3303 }
3304 case IntrinsicHelper::HLSputBoolean: {
TDYa1275a26d442012-07-26 18:58:38 -07003305 Expand_HLSput(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07003306 return NULL;
3307 }
3308 case IntrinsicHelper::HLSputByte: {
TDYa1275a26d442012-07-26 18:58:38 -07003309 Expand_HLSput(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07003310 return NULL;
3311 }
3312 case IntrinsicHelper::HLSputChar: {
TDYa1275a26d442012-07-26 18:58:38 -07003313 Expand_HLSput(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07003314 return NULL;
3315 }
3316 case IntrinsicHelper::HLSputShort: {
TDYa1275a26d442012-07-26 18:58:38 -07003317 Expand_HLSput(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07003318 return NULL;
3319 }
3320 case IntrinsicHelper::HLSputFloat: {
TDYa1275a26d442012-07-26 18:58:38 -07003321 Expand_HLSput(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07003322 return NULL;
3323 }
3324 case IntrinsicHelper::HLSputWide: {
TDYa1275a26d442012-07-26 18:58:38 -07003325 Expand_HLSput(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07003326 return NULL;
3327 }
3328 case IntrinsicHelper::HLSputDouble: {
TDYa1275a26d442012-07-26 18:58:38 -07003329 Expand_HLSput(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07003330 return NULL;
3331 }
3332 case IntrinsicHelper::HLSputObject: {
TDYa1275a26d442012-07-26 18:58:38 -07003333 Expand_HLSput(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07003334 return NULL;
3335 }
3336
3337 //==- High-level Monitor -----------------------------------------------==//
3338 case IntrinsicHelper::MonitorEnter: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003339 Expand_MonitorEnter(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003340 return NULL;
3341 }
3342 case IntrinsicHelper::MonitorExit: {
TDYa127f71bf5a2012-07-29 20:09:52 -07003343 Expand_MonitorExit(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07003344 return NULL;
3345 }
3346
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003347 //==- Shadow Frame -----------------------------------------------------==//
3348 case IntrinsicHelper::AllocaShadowFrame: {
3349 Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
3350 return NULL;
3351 }
3352 case IntrinsicHelper::SetShadowFrameEntry: {
3353 Expand_SetShadowFrameEntry(call_inst.getArgOperand(0),
3354 call_inst.getArgOperand(1));
3355 return NULL;
3356 }
3357 case IntrinsicHelper::PopShadowFrame: {
3358 Expand_PopShadowFrame();
3359 return NULL;
3360 }
3361 case IntrinsicHelper::UpdateDexPC: {
3362 Expand_UpdateDexPC(call_inst.getArgOperand(0));
3363 return NULL;
3364 }
TDYa127a1b21852012-07-23 03:20:39 -07003365
Logan Chien75e4b602012-07-23 14:24:12 -07003366 //==- Comparison -------------------------------------------------------==//
3367 case IntrinsicHelper::CmplFloat:
3368 case IntrinsicHelper::CmplDouble: {
3369 return Expand_FPCompare(call_inst.getArgOperand(0),
3370 call_inst.getArgOperand(1),
3371 false);
3372 }
3373 case IntrinsicHelper::CmpgFloat:
3374 case IntrinsicHelper::CmpgDouble: {
3375 return Expand_FPCompare(call_inst.getArgOperand(0),
3376 call_inst.getArgOperand(1),
3377 true);
3378 }
3379 case IntrinsicHelper::CmpLong: {
3380 return Expand_LongCompare(call_inst.getArgOperand(0),
3381 call_inst.getArgOperand(1));
3382 }
TDYa127a1b21852012-07-23 03:20:39 -07003383
Logan Chien75e4b602012-07-23 14:24:12 -07003384 //==- Switch -----------------------------------------------------------==//
3385 case greenland::IntrinsicHelper::SparseSwitch: {
TDYa1275e869b62012-07-25 00:45:39 -07003386 // Nothing to be done.
Logan Chien75e4b602012-07-23 14:24:12 -07003387 return NULL;
3388 }
3389 case greenland::IntrinsicHelper::PackedSwitch: {
TDYa1275e869b62012-07-25 00:45:39 -07003390 // Nothing to be done.
Logan Chien75e4b602012-07-23 14:24:12 -07003391 return NULL;
3392 }
3393
3394 //==- Const ------------------------------------------------------------==//
Logan Chiend54a23d2012-07-24 11:19:23 -07003395 case greenland::IntrinsicHelper::ConstInt:
Logan Chien75e4b602012-07-23 14:24:12 -07003396 case greenland::IntrinsicHelper::ConstLong: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003397 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07003398 }
3399 case greenland::IntrinsicHelper::ConstFloat: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003400 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3401 irb_.getJFloatTy());
Logan Chien75e4b602012-07-23 14:24:12 -07003402 }
3403 case greenland::IntrinsicHelper::ConstDouble: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003404 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3405 irb_.getJDoubleTy());
3406 }
3407 case greenland::IntrinsicHelper::ConstObj: {
3408 LOG(FATAL) << "ConstObj should not occur at all";
Logan Chien75e4b602012-07-23 14:24:12 -07003409 return NULL;
3410 }
3411
3412 //==- Method Info ------------------------------------------------------==//
3413 case greenland::IntrinsicHelper::MethodInfo: {
TDYa1275e869b62012-07-25 00:45:39 -07003414 // Nothing to be done.
Logan Chien75e4b602012-07-23 14:24:12 -07003415 return NULL;
3416 }
3417
3418 //==- Copy -------------------------------------------------------------==//
Logan Chiend54a23d2012-07-24 11:19:23 -07003419 case greenland::IntrinsicHelper::CopyInt:
3420 case greenland::IntrinsicHelper::CopyFloat:
3421 case greenland::IntrinsicHelper::CopyLong:
TDYa1275e869b62012-07-25 00:45:39 -07003422 case greenland::IntrinsicHelper::CopyDouble:
Logan Chien75e4b602012-07-23 14:24:12 -07003423 case greenland::IntrinsicHelper::CopyObj: {
Logan Chiend54a23d2012-07-24 11:19:23 -07003424 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07003425 }
3426
3427 //==- Shift ------------------------------------------------------------==//
3428 case greenland::IntrinsicHelper::SHLLong: {
3429 return Expand_IntegerShift(call_inst.getArgOperand(0),
3430 call_inst.getArgOperand(1),
3431 kIntegerSHL, kLong);
3432 }
3433 case greenland::IntrinsicHelper::SHRLong: {
3434 return Expand_IntegerShift(call_inst.getArgOperand(0),
3435 call_inst.getArgOperand(1),
3436 kIntegerSHR, kLong);
3437 }
3438 case greenland::IntrinsicHelper::USHRLong: {
3439 return Expand_IntegerShift(call_inst.getArgOperand(0),
3440 call_inst.getArgOperand(1),
3441 kIntegerUSHR, kLong);
3442 }
3443 case greenland::IntrinsicHelper::SHLInt: {
3444 return Expand_IntegerShift(call_inst.getArgOperand(0),
3445 call_inst.getArgOperand(1),
3446 kIntegerSHL, kInt);
3447 }
3448 case greenland::IntrinsicHelper::SHRInt: {
3449 return Expand_IntegerShift(call_inst.getArgOperand(0),
3450 call_inst.getArgOperand(1),
3451 kIntegerSHR, kInt);
3452 }
3453 case greenland::IntrinsicHelper::USHRInt: {
3454 return Expand_IntegerShift(call_inst.getArgOperand(0),
3455 call_inst.getArgOperand(1),
3456 kIntegerUSHR, kInt);
3457 }
3458
3459 //==- Conversion -------------------------------------------------------==//
TDYa127a1b21852012-07-23 03:20:39 -07003460 case IntrinsicHelper::IntToChar: {
3461 return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
3462 irb_.getJIntTy());
3463 }
3464 case IntrinsicHelper::IntToShort: {
3465 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
3466 irb_.getJIntTy());
3467 }
3468 case IntrinsicHelper::IntToByte: {
3469 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
3470 irb_.getJIntTy());
3471 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003472
Logan Chien75e4b602012-07-23 14:24:12 -07003473 //==- Unknown Cases ----------------------------------------------------==//
3474 case IntrinsicHelper::MaxIntrinsicId:
3475 case IntrinsicHelper::UnknownId:
3476 //default:
3477 // NOTE: "default" is intentionally commented so that C/C++ compiler will
3478 // give some warning on unmatched cases.
3479 // NOTE: We should not implement these cases.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003480 break;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003481 }
Logan Chien75e4b602012-07-23 14:24:12 -07003482 UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07003483 return NULL;
3484}
3485
3486} // anonymous namespace
3487
3488namespace art {
3489namespace compiler_llvm {
3490
3491llvm::FunctionPass*
3492CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb) {
3493 return new GBCExpanderPass(intrinsic_helper, irb);
3494}
3495
3496} // namespace compiler_llvm
3497} // namespace art