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