blob: a0693a832f23fbae67f90c733d1755d5c0417605 [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>
29#include <llvm/Pass.h>
30#include <llvm/Support/CFG.h>
31#include <llvm/Support/InstIterator.h>
32
33#include <vector>
34
35using namespace art;
36using namespace compiler_llvm;
37
38using art::greenland::IntrinsicHelper;
39
40namespace {
41
42class GBCExpanderPass : public llvm::FunctionPass {
43 private:
44 const IntrinsicHelper& intrinsic_helper_;
45 IRBuilder& irb_;
46
47 llvm::LLVMContext& context_;
48 RuntimeSupportBuilder& rtb_;
49
50 private:
51 llvm::AllocaInst* shadow_frame_;
52 llvm::Value* old_shadow_frame_;
53 uint32_t shadow_frame_size_;
54
55 private:
TDYa1275e869b62012-07-25 00:45:39 -070056 // TODO: Init these fields
57 Compiler* compiler_;
58
59 const DexFile* dex_file_;
60 DexCache* dex_cache_;
61 const DexFile::CodeItem* code_item_;
62
63 OatCompilationUnit* oat_compilation_unit_;
64
65 uint32_t method_idx_;
66
67 llvm::Function* func_;
68
69 std::vector<llvm::BasicBlock*> basic_blocks_;
70
71 std::vector<llvm::BasicBlock*> basic_block_landing_pads_;
72 llvm::BasicBlock* basic_block_unwind_;
73
74 private:
Shih-wei Liao21d28f52012-06-12 05:55:00 -070075 //----------------------------------------------------------------------------
Logan Chien75e4b602012-07-23 14:24:12 -070076 // Constant for GBC expansion
77 //----------------------------------------------------------------------------
78 enum IntegerShiftKind {
79 kIntegerSHL,
80 kIntegerSHR,
81 kIntegerUSHR,
82 };
83
84 private:
85 //----------------------------------------------------------------------------
Shih-wei Liao21d28f52012-06-12 05:55:00 -070086 // Helper function for GBC expansion
87 //----------------------------------------------------------------------------
88
Shih-wei Liao21d28f52012-06-12 05:55:00 -070089 llvm::Value* ExpandToRuntime(runtime_support::RuntimeId rt,
90 llvm::CallInst& inst);
91
TDYa1275e869b62012-07-25 00:45:39 -070092 uint64_t LV2UInt(llvm::Value* lv) {
93 return llvm::cast<llvm::ConstantInt>(lv)->getZExtValue();
94 }
95
96 int64_t LV2SInt(llvm::Value* lv) {
97 return llvm::cast<llvm::ConstantInt>(lv)->getSExtValue();
98 }
99
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700100 private:
101 // TODO: Almost all Emit* are directly copy-n-paste from MethodCompiler.
102 // Refactor these utility functions from MethodCompiler to avoid forking.
103
104 bool EmitStackOverflowCheck(llvm::Instruction* first_non_alloca);
105
106 //----------------------------------------------------------------------------
107 // Dex cache code generation helper function
108 //----------------------------------------------------------------------------
109 llvm::Value* EmitLoadDexCacheAddr(MemberOffset dex_cache_offset);
110
111 llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
112
113 llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
114
115 llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
116
117 llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
118
119 //----------------------------------------------------------------------------
120 // Code generation helper function
121 //----------------------------------------------------------------------------
122 llvm::Value* EmitLoadMethodObjectAddr();
123
124 llvm::Value* EmitLoadArrayLength(llvm::Value* array);
125
126 llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
127
128 llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
129 llvm::Value* this_addr);
130
131 llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
132 llvm::Value* index_value,
133 JType elem_jty);
134
135 private:
136 //----------------------------------------------------------------------------
137 // Expand Greenland intrinsics
138 //----------------------------------------------------------------------------
139 void Expand_TestSuspend(llvm::CallInst& call_inst);
140
TDYa1279a129452012-07-19 03:10:08 -0700141 void Expand_MarkGCCard(llvm::CallInst& call_inst);
142
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700143 llvm::Value* Expand_GetException();
144
145 llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
146
147 llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
148
149 void Expand_LockObject(llvm::Value* obj);
150
151 void Expand_UnlockObject(llvm::Value* obj);
152
153 llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
154 llvm::Value* index_value,
155 JType elem_jty);
156
157 void Expand_ArrayPut(llvm::Value* new_value,
158 llvm::Value* array_addr,
159 llvm::Value* index_value,
160 JType elem_jty);
161
162 void Expand_FilledNewArray(llvm::CallInst& call_inst);
163
164 llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
165 llvm::Value* is_volatile_value,
166 llvm::Value* object_addr,
167 JType field_jty);
168
169 void Expand_IPutFast(llvm::Value* field_offset_value,
170 llvm::Value* is_volatile_value,
171 llvm::Value* object_addr,
172 llvm::Value* new_value,
173 JType field_jty);
174
175 llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
176 llvm::Value* field_offset_value,
177 llvm::Value* is_volatile_value,
178 JType field_jty);
179
180 void Expand_SPutFast(llvm::Value* static_storage_addr,
181 llvm::Value* field_offset_value,
182 llvm::Value* is_volatile_value,
183 llvm::Value* new_value,
184 JType field_jty);
185
186 llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
187
188 llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
189
190 llvm::Value*
191 Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
192
193 llvm::Value*
194 Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
195 llvm::Value* this_addr);
196
197 llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
198
199 llvm::Value* Expand_DivRem(llvm::Value* dividend, llvm::Value* divisor,
200 bool is_div, JType op_jty);
201
202 void Expand_AllocaShadowFrame(llvm::Value* num_entry_value);
203
204 void Expand_SetShadowFrameEntry(llvm::Value* obj, llvm::Value* entry_idx);
205
206 void Expand_PopShadowFrame();
207
208 void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
209
TDYa127a1b21852012-07-23 03:20:39 -0700210 //----------------------------------------------------------------------------
211 // Quick
212 //----------------------------------------------------------------------------
213
214 llvm::Value* Expand_FPCompare(llvm::Value* src1_value,
215 llvm::Value* src2_value,
216 bool gt_bias);
217
218 llvm::Value* Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value);
219
220 llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
221 llvm::Value* cmp_lt);
222
TDYa1275e869b62012-07-25 00:45:39 -0700223 class ScopedExpandToBasicBlock {
224 public:
225 ScopedExpandToBasicBlock(IRBuilder& irb, llvm::Instruction* expand_inst)
226 : irb_(irb), expand_inst_(expand_inst) {
227 llvm::Function* func = expand_inst_->getParent()->getParent();
228 begin_bb_ = llvm::BasicBlock::Create(irb_.getContext(),
229 "",
230 func);
231 irb_.SetInsertPoint(begin_bb_);
232 }
233
234 ~ScopedExpandToBasicBlock() {
235 llvm::BasicBlock* end_bb = irb_.GetInsertBlock();
236 SplitAndInsertBasicBlocksAfter(*expand_inst_, begin_bb_, end_bb);
237 }
238
239 private:
240 // Split the basic block containing INST at INST and insert a sequence of
241 // basic blocks with a single entry at BEGIN_BB and a single exit at END_BB
242 // before INST.
243 llvm::BasicBlock*
244 SplitAndInsertBasicBlocksAfter(llvm::BasicBlock::iterator inst,
245 llvm::BasicBlock* begin_bb,
246 llvm::BasicBlock* end_bb);
247 private:
248 IRBuilder& irb_;
249 llvm::Instruction* expand_inst_;
250 llvm::BasicBlock* begin_bb_;
251 };
252
253 llvm::Value* Expand_HLIGet(llvm::CallInst& call_inst, JType field_jty);
254 void Expand_HLIPut(llvm::CallInst& call_inst, JType field_jty);
255
256 void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
257
258 void EmitUpdateDexPC(uint32_t dex_pc);
259
260 void EmitGuard_DivZeroException(uint32_t dex_pc,
261 llvm::Value* denominator,
262 JType op_jty);
263
264 void EmitGuard_NullPointerException(uint32_t dex_pc,
265 llvm::Value* object);
266
267 void EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
268 llvm::Value* array,
269 llvm::Value* index);
270
271 void EmitGuard_ArrayException(uint32_t dex_pc,
272 llvm::Value* array,
273 llvm::Value* index);
274
275 llvm::FunctionType* GetFunctionType(uint32_t method_idx, bool is_static);
276
277 llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
278
279 llvm::BasicBlock* CreateBasicBlockWithDexPC(uint32_t dex_pc,
280 const char* postfix);
281
282 int32_t GetTryItemOffset(uint32_t dex_pc);
283
284 llvm::BasicBlock* GetLandingPadBasicBlock(uint32_t dex_pc);
285
286 llvm::BasicBlock* GetUnwindBasicBlock();
287
288 void EmitGuard_ExceptionLandingPad(uint32_t dex_pc);
289
290 void EmitBranchExceptionLandingPad(uint32_t dex_pc);
291
Logan Chien75e4b602012-07-23 14:24:12 -0700292 //----------------------------------------------------------------------------
293 // Expand Arithmetic Helper Intrinsics
294 //----------------------------------------------------------------------------
295
296 llvm::Value* Expand_IntegerShift(llvm::Value* src1_value,
297 llvm::Value* src2_value,
298 IntegerShiftKind kind,
299 JType op_jty);
300
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700301 public:
302 static char ID;
303
304 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb)
305 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
306 context_(irb.getContext()), rtb_(irb.Runtime())
307 { }
308
309 bool runOnFunction(llvm::Function& func);
310
311 private:
312 bool InsertStackOverflowCheck(llvm::Function& func);
313
314 llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
315 llvm::CallInst& call_inst);
316
317};
318
319char GBCExpanderPass::ID = 0;
320
321bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
TDYa127b672d1e2012-06-28 21:21:45 -0700322 // Runtime support or stub
323 if (func.getName().startswith("art_") || func.getName().startswith("Art")) {
324 return false;
325 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700326 bool changed;
327
TDYa127b672d1e2012-06-28 21:21:45 -0700328 // TODO: Use intrinsic.
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700329 changed = InsertStackOverflowCheck(func);
330
331 std::list<std::pair<llvm::CallInst*,
332 IntrinsicHelper::IntrinsicId> > work_list;
333
334 for (llvm::inst_iterator inst_iter = llvm::inst_begin(func),
335 inst_end = llvm::inst_end(func); inst_iter != inst_end; inst_iter++) {
336 // Only CallInst with its called function is dexlang intrinsic need to
337 // process
338 llvm::Instruction* inst = &*inst_iter;
339 if (llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst)) {
340 const llvm::Function* callee = call_inst->getCalledFunction();
341
342 if (callee != NULL) {
343 IntrinsicHelper::IntrinsicId intr_id =
344 intrinsic_helper_.GetIntrinsicId(callee);
345
346 if (intr_id != IntrinsicHelper::UnknownId) {
347 work_list.push_back(std::make_pair(call_inst, intr_id));
348 }
349 }
350 }
351 }
352
353 changed |= !work_list.empty();
354
355 shadow_frame_ = NULL;
356 old_shadow_frame_ = NULL;
357 shadow_frame_size_ = 0;
TDYa1275e869b62012-07-25 00:45:39 -0700358 func_ = &func;
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700359
360 // Remove the instruction containing in the work_list
361 while (!work_list.empty()) {
362 llvm::CallInst* intr_inst = work_list.front().first;
363 IntrinsicHelper::IntrinsicId intr_id = work_list.front().second;
364
365 // Remove the instruction from work list
366 work_list.pop_front();
367
368 // Move the IRBuilder insert pointer
369 irb_.SetInsertPoint(intr_inst);
370
371 // Process the expansion
372 llvm::Value* new_value = ExpandIntrinsic(intr_id, *intr_inst);
373
374 // Use the new value from the expansion
375 if (new_value != NULL) {
376 intr_inst->replaceAllUsesWith(new_value);
377 }
378
379 // Remove the intrinsic instruction
380 intr_inst->eraseFromParent();
381 }
382
383 VERIFY_LLVM_FUNCTION(func);
384
385 return changed;
386}
387
388llvm::BasicBlock*
TDYa1275e869b62012-07-25 00:45:39 -0700389GBCExpanderPass::ScopedExpandToBasicBlock::
390SplitAndInsertBasicBlocksAfter(llvm::BasicBlock::iterator inst,
391 llvm::BasicBlock* begin_bb,
392 llvm::BasicBlock* end_bb) {
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700393 llvm::BasicBlock* original = inst->getParent();
394 llvm::Function* parent = original->getParent();
395
396 // 1. Create a new basic block A after ORIGINAL
397 llvm::BasicBlock *insert_before =
398 llvm::next(llvm::Function::iterator(original)).getNodePtrUnchecked();
399 llvm::BasicBlock* a =
TDYa1275e869b62012-07-25 00:45:39 -0700400 llvm::BasicBlock::Create(irb_.getContext(), "", parent, insert_before);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700401
402 // 2. Move all instructions in ORIGINAL after INST (included) to A
403 a->getInstList().splice(a->end(), original->getInstList(),
404 inst, original->end());
405
406 // 3. Add an unconditional branch in ORIGINAL to begin_bb
407 llvm::BranchInst::Create(begin_bb, original);
408
409 // 4. Add an unconditional branch in END_BB to A
410 llvm::BranchInst::Create(a, end_bb);
411
412 // 5. Update the PHI nodes in the successors of A. Update the PHI node entry
413 // with incoming basic block from ORIGINAL to A
414 for (llvm::succ_iterator succ_iter = llvm::succ_begin(a),
415 succ_end = llvm::succ_end(a); succ_iter != succ_end; succ_iter++) {
416 llvm::BasicBlock* succ = *succ_iter;
417 llvm::PHINode* phi;
418 for (llvm::BasicBlock::iterator inst_iter = succ->begin();
419 (phi = llvm::dyn_cast<llvm::PHINode>(inst_iter)); ++inst_iter) {
420 int idx;
421 while ((idx = phi->getBasicBlockIndex(original)) != -1) {
422 phi->setIncomingBlock(static_cast<unsigned>(idx), a);
423 }
424 }
425 }
426
427 return a;
428}
429
430llvm::Value* GBCExpanderPass::ExpandToRuntime(runtime_support::RuntimeId rt,
431 llvm::CallInst& inst) {
432 // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
433 // the arguments passed to the GBC intrinsic are as the same as IBC runtime
434 // function, therefore only called function is needed to change.
435 unsigned num_args = inst.getNumArgOperands();
436
437 if (num_args <= 0) {
438 return irb_.CreateCall(irb_.GetRuntime(rt));
439 } else {
440 std::vector<llvm::Value*> args;
441 for (unsigned i = 0; i < num_args; i++) {
442 args.push_back(inst.getArgOperand(i));
443 }
444
445 return irb_.CreateCall(irb_.GetRuntime(rt), args);
446 }
447}
448
449bool
450GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
TDYa1275e869b62012-07-25 00:45:39 -0700451 ScopedExpandToBasicBlock eb(irb_, first_non_alloca);
452
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700453 llvm::Function* func = first_non_alloca->getParent()->getParent();
454 llvm::Module* module = func->getParent();
455
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700456 // Call llvm intrinsic function to get frame address.
457 llvm::Function* frameaddress =
458 llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
459
460 // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
461 llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
462
463 // Cast i8* to int
464 frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
465
466 // Get thread.stack_end_
467 llvm::Value* stack_end =
468 irb_.Runtime().EmitLoadFromThreadOffset(Thread::StackEndOffset().Int32Value(),
469 irb_.getPtrEquivIntTy(),
470 kTBAARuntimeInfo);
471
472 // Check the frame address < thread.stack_end_ ?
473 llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
474
475 llvm::BasicBlock* block_exception =
476 llvm::BasicBlock::Create(context_, "stack_overflow", func);
477
478 llvm::BasicBlock* block_continue =
479 llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
480
481 irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
482
483 // If stack overflow, throw exception.
484 irb_.SetInsertPoint(block_exception);
485 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowStackOverflowException));
486
487 // Unwind.
488 llvm::Type* ret_type = func->getReturnType();
489 if (ret_type->isVoidTy()) {
490 irb_.CreateRetVoid();
491 } else {
492 // The return value is ignored when there's an exception. MethodCompiler
493 // returns zero value under the the corresponding return type in this case.
494 // GBCExpander returns LLVM undef value here for brevity
495 irb_.CreateRet(llvm::UndefValue::get(ret_type));
496 }
497
498 irb_.SetInsertPoint(block_continue);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700499 return true;
500}
501
502llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(MemberOffset offset) {
503 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
504
505 return irb_.LoadFromObjectOffset(method_object_addr,
506 offset.Int32Value(),
507 irb_.getJObjectTy(),
508 kTBAAConstJObject);
509}
510
511llvm::Value*
512GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
513 llvm::Value* static_storage_dex_cache_addr =
514 EmitLoadDexCacheAddr(Method::DexCacheInitializedStaticStorageOffset());
515
516 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
517
518 return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
519}
520
521llvm::Value*
522GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
523 llvm::Value* resolved_type_dex_cache_addr =
524 EmitLoadDexCacheAddr(Method::DexCacheResolvedTypesOffset());
525
526 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
527
528 return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
529}
530
531llvm::Value* GBCExpanderPass::
532EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
533 llvm::Value* resolved_method_dex_cache_addr =
534 EmitLoadDexCacheAddr(Method::DexCacheResolvedMethodsOffset());
535
536 llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
537
538 return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
539}
540
541llvm::Value* GBCExpanderPass::
542EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
543 llvm::Value* string_dex_cache_addr =
544 EmitLoadDexCacheAddr(Method::DexCacheStringsOffset());
545
546 llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
547
548 return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
549}
550
551llvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
552 llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
553 return parent_func->arg_begin();
554}
555
556llvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
557 // Load array length
558 return irb_.LoadFromObjectOffset(array,
559 Array::LengthOffset().Int32Value(),
560 irb_.getJIntTy(),
561 kTBAAConstJObject);
562
563}
564
565llvm::Value*
566GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
567 llvm::Value* callee_method_object_field_addr =
568 EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
569
570 return irb_.CreateLoad(callee_method_object_field_addr, kTBAAJRuntime);
571}
572
573llvm::Value* GBCExpanderPass::
574EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
575 // Load class object of *this* pointer
576 llvm::Value* class_object_addr =
577 irb_.LoadFromObjectOffset(this_addr,
578 Object::ClassOffset().Int32Value(),
579 irb_.getJObjectTy(),
580 kTBAAConstJObject);
581
582 // Load vtable address
583 llvm::Value* vtable_addr =
584 irb_.LoadFromObjectOffset(class_object_addr,
585 Class::VTableOffset().Int32Value(),
586 irb_.getJObjectTy(),
587 kTBAAConstJObject);
588
589 // Load callee method object
590 llvm::Value* vtable_idx_value =
591 irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
592
593 llvm::Value* method_field_addr =
594 EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
595
596 return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
597}
598
599// Emit Array GetElementPtr
600llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
601 llvm::Value* index_value,
602 JType elem_jty) {
603
604 int data_offset;
605 if (elem_jty == kLong || elem_jty == kDouble ||
606 (elem_jty == kObject && sizeof(uint64_t) == sizeof(Object*))) {
607 data_offset = Array::DataOffset(sizeof(int64_t)).Int32Value();
608 } else {
609 data_offset = Array::DataOffset(sizeof(int32_t)).Int32Value();
610 }
611
612 llvm::Constant* data_offset_value =
613 irb_.getPtrEquivInt(data_offset);
614
615 llvm::Type* elem_type = irb_.getJType(elem_jty, kArray);
616
617 llvm::Value* array_data_addr =
618 irb_.CreatePtrDisp(array_addr, data_offset_value,
619 elem_type->getPointerTo());
620
621 return irb_.CreateGEP(array_data_addr, index_value);
622}
623
624void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
TDYa1275e869b62012-07-25 00:45:39 -0700625 ScopedExpandToBasicBlock eb(irb_, &call_inst);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700626 irb_.Runtime().EmitTestSuspend();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700627 return;
628}
629
TDYa1279a129452012-07-19 03:10:08 -0700630void GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
TDYa1275e869b62012-07-25 00:45:39 -0700631 ScopedExpandToBasicBlock eb(irb_, &call_inst);
TDYa1279a129452012-07-19 03:10:08 -0700632 irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
TDYa1279a129452012-07-19 03:10:08 -0700633 return;
634}
635
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700636llvm::Value* GBCExpanderPass::Expand_GetException() {
637 // Get thread-local exception field address
638 llvm::Value* exception_object_addr =
639 irb_.Runtime().EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
640 irb_.getJObjectTy(),
641 kTBAAJRuntime);
642
643 // Set thread-local exception field address to NULL
644 irb_.Runtime().EmitStoreToThreadOffset(Thread::ExceptionOffset().Int32Value(),
645 irb_.getJNull(),
646 kTBAAJRuntime);
647
648 return exception_object_addr;
649}
650
651llvm::Value*
652GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
653 uint32_t string_idx =
654 llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
655
656 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
657
658 return irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
659}
660
661llvm::Value*
662GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
663 uint32_t type_idx =
664 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
665
666 llvm::Value* type_field_addr =
667 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
668
669 return irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
670}
671
672void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
TDYa1275e869b62012-07-25 00:45:39 -0700673 ScopedExpandToBasicBlock eb(irb_, irb_.GetInsertPoint());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700674 rtb_.EmitLockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700675 return;
676}
677
678void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
TDYa1275e869b62012-07-25 00:45:39 -0700679 ScopedExpandToBasicBlock eb(irb_, irb_.GetInsertPoint());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700680 rtb_.EmitUnlockObject(obj);
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700681 return;
682}
683
684llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
685 llvm::Value* index_value,
686 JType elem_jty) {
687 llvm::Value* array_elem_addr =
688 EmitArrayGEP(array_addr, index_value, elem_jty);
689
690 return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
691}
692
693void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
694 llvm::Value* array_addr,
695 llvm::Value* index_value,
696 JType elem_jty) {
697 llvm::Value* array_elem_addr =
698 EmitArrayGEP(array_addr, index_value, elem_jty);
699
700 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
701
702 return;
703}
704
705void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
706 // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
707 llvm::Value* array = call_inst.getArgOperand(0);
708
709 uint32_t element_jty =
710 llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
711
712 DCHECK(call_inst.getNumArgOperands() > 2);
713 unsigned num_elements = (call_inst.getNumArgOperands() - 2);
714
715 bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
716
717 uint32_t alignment;
718 llvm::Constant* elem_size;
719 llvm::PointerType* field_type;
720
721 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
722 // as the element, thus we are only checking 2 cases: primitive int and
723 // non-primitive type.
724 if (is_elem_int_ty) {
725 alignment = sizeof(int32_t);
726 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
727 field_type = irb_.getJIntTy()->getPointerTo();
728 } else {
729 alignment = irb_.getSizeOfPtrEquivInt();
730 elem_size = irb_.getSizeOfPtrEquivIntValue();
731 field_type = irb_.getJObjectTy()->getPointerTo();
732 }
733
734 llvm::Value* data_field_offset =
735 irb_.getPtrEquivInt(Array::DataOffset(alignment).Int32Value());
736
737 llvm::Value* data_field_addr =
738 irb_.CreatePtrDisp(array, data_field_offset, field_type);
739
740 for (unsigned i = 0; i < num_elements; ++i) {
741 // Values to fill the array begin at the 3rd argument
742 llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
743
744 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
745
746 data_field_addr =
747 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
748 }
749
750 return;
751}
752
753llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
754 llvm::Value* /*is_volatile_value*/,
755 llvm::Value* object_addr,
756 JType field_jty) {
757 int field_offset =
758 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
759
760 DCHECK_GE(field_offset, 0);
761
762 llvm::PointerType* field_type =
763 irb_.getJType(field_jty, kField)->getPointerTo();
764
765 field_offset_value = irb_.getPtrEquivInt(field_offset);
766
767 llvm::Value* field_addr =
768 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
769
770 // TODO: Check is_volatile. We need to generate atomic load instruction
771 // when is_volatile is true.
772 return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
773}
774
775void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
776 llvm::Value* /* is_volatile_value */,
777 llvm::Value* object_addr,
778 llvm::Value* new_value,
779 JType field_jty) {
780 int field_offset =
781 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
782
783 DCHECK_GE(field_offset, 0);
784
785 llvm::PointerType* field_type =
786 irb_.getJType(field_jty, kField)->getPointerTo();
787
788 field_offset_value = irb_.getPtrEquivInt(field_offset);
789
790 llvm::Value* field_addr =
791 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
792
793 // TODO: Check is_volatile. We need to generate atomic store instruction
794 // when is_volatile is true.
795 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
796
797 return;
798}
799
800llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
801 llvm::Value* field_offset_value,
802 llvm::Value* /*is_volatile_value*/,
803 JType field_jty) {
804 int field_offset =
805 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
806
807 DCHECK_GE(field_offset, 0);
808
809 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
810
811 llvm::Value* static_field_addr =
812 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
813 irb_.getJType(field_jty, kField)->getPointerTo());
814
815 // TODO: Check is_volatile. We need to generate atomic store instruction
816 // when is_volatile is true.
817 return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
818}
819
820void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
821 llvm::Value* field_offset_value,
822 llvm::Value* /* is_volatile_value */,
823 llvm::Value* new_value,
824 JType field_jty) {
825 int field_offset =
826 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
827
828 DCHECK_GE(field_offset, 0);
829
830 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
831
832 llvm::Value* static_field_addr =
833 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
834 irb_.getJType(field_jty, kField)->getPointerTo());
835
836 // TODO: Check is_volatile. We need to generate atomic store instruction
837 // when is_volatile is true.
838 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
839
840 return;
841}
842
843llvm::Value*
844GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
845 return irb_.LoadFromObjectOffset(method_object_addr,
846 Method::DeclaringClassOffset().Int32Value(),
847 irb_.getJObjectTy(),
848 kTBAAConstJObject);
849}
850
851llvm::Value*
852GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
853 uint32_t type_idx =
854 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
855
856 llvm::Value* storage_field_addr =
857 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
858
859 return irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
860}
861
862llvm::Value*
863GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
864 uint32_t callee_method_idx =
865 llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
866
867 return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
868}
869
870llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
871 llvm::Value* vtable_idx_value,
872 llvm::Value* this_addr) {
873 int vtable_idx =
874 llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
875
876 return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
877}
878
879llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
880 // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
881 llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
882 unsigned num_args = call_inst.getNumArgOperands();
883 llvm::Type* ret_type = call_inst.getType();
884
885 // Determine the function type of the callee method
886 std::vector<llvm::Type*> args_type;
887 std::vector<llvm::Value*> args;
888 for (unsigned i = 0; i < num_args; i++) {
889 args.push_back(call_inst.getArgOperand(i));
890 args_type.push_back(args[i]->getType());
891 }
892
893 llvm::FunctionType* callee_method_type =
894 llvm::FunctionType::get(ret_type, args_type, false);
895
896 llvm::Value* code_addr =
897 irb_.LoadFromObjectOffset(callee_method_object_addr,
898 Method::GetCodeOffset().Int32Value(),
899 callee_method_type->getPointerTo(),
900 kTBAAJRuntime);
901
902 // Invoke callee
903 llvm::Value* retval = irb_.CreateCall(code_addr, args);
904
905 return retval;
906}
907
908llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::Value* dividend,
909 llvm::Value* divisor,
910 bool is_div, JType op_jty) {
911 // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
912
913 // Check the special case: MININT / -1 = MININT
914 // That case will cause overflow, which is undefined behavior in llvm.
915 // So we check the divisor is -1 or not, if the divisor is -1, we do
916 // the special path to avoid undefined behavior.
917 llvm::Type* op_type = irb_.getJType(op_jty, kAccurate);
918 llvm::Value* zero = irb_.getJZero(op_jty);
919 llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
920
TDYa1275e869b62012-07-25 00:45:39 -0700921 ScopedExpandToBasicBlock eb(irb_, irb_.GetInsertPoint());
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700922
TDYa1275e869b62012-07-25 00:45:39 -0700923 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700924 llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
925 llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
926 llvm::BasicBlock* neg_one_cont =
927 llvm::BasicBlock::Create(context_, "", parent);
928
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700929 llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
930 irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
931
932 // If divisor == -1
933 irb_.SetInsertPoint(eq_neg_one);
934 llvm::Value* eq_result;
935 if (is_div) {
936 // We can just change from "dividend div -1" to "neg dividend". The sub
937 // don't care the sign/unsigned because of two's complement representation.
938 // And the behavior is what we want:
939 // -(2^n) (2^n)-1
940 // MININT < k <= MAXINT -> mul k -1 = -k
941 // MININT == k -> mul k -1 = k
942 //
943 // LLVM use sub to represent 'neg'
944 eq_result = irb_.CreateSub(zero, dividend);
945 } else {
946 // Everything modulo -1 will be 0.
947 eq_result = zero;
948 }
949 irb_.CreateBr(neg_one_cont);
950
951 // If divisor != -1, just do the division.
952 irb_.SetInsertPoint(ne_neg_one);
953 llvm::Value* ne_result;
954 if (is_div) {
955 ne_result = irb_.CreateSDiv(dividend, divisor);
956 } else {
957 ne_result = irb_.CreateSRem(dividend, divisor);
958 }
959 irb_.CreateBr(neg_one_cont);
960
961 irb_.SetInsertPoint(neg_one_cont);
962 llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
963 result->addIncoming(eq_result, eq_neg_one);
964 result->addIncoming(ne_result, ne_neg_one);
965
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700966 return result;
967}
968
969void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value) {
970 // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
971 // MethodCompiler::EmitPushShadowFrame
972 shadow_frame_size_ =
973 llvm::cast<llvm::ConstantInt>(num_entry_value)->getZExtValue();
974
975 llvm::StructType* shadow_frame_type =
976 irb_.getShadowFrameTy(shadow_frame_size_);
977
978 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
979
980 // Alloca a pointer to old shadow frame
981 old_shadow_frame_ =
982 irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
983
984 // Zero-initialization of the shadow frame table
985 llvm::Value* shadow_frame_table =
986 irb_.CreateConstGEP2_32(shadow_frame_, 0, 1);
987 llvm::Type* table_type = shadow_frame_type->getElementType(1);
988
989 llvm::ConstantAggregateZero* zero_initializer =
990 llvm::ConstantAggregateZero::get(table_type);
991
992 irb_.CreateStore(zero_initializer, shadow_frame_table, kTBAAShadowFrame);
993
994 // Push the shadow frame
995 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
996
997 // Push the shadow frame
998 llvm::Value* shadow_frame_upcast =
999 irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
1000
1001 llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
1002 method_object_addr,
1003 shadow_frame_size_);
1004
1005 irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
1006
1007 return;
1008}
1009
1010void GBCExpanderPass::Expand_SetShadowFrameEntry(llvm::Value* obj,
1011 llvm::Value* entry_idx) {
1012 DCHECK(shadow_frame_ != NULL);
1013
1014 llvm::Value* gep_index[] = {
1015 irb_.getInt32(0), // No pointer displacement
1016 irb_.getInt32(1), // SIRT
1017 entry_idx // Pointer field
1018 };
1019
1020 llvm::Value* entry_addr = irb_.CreateGEP(shadow_frame_, gep_index);
1021 irb_.CreateStore(obj, entry_addr, kTBAAShadowFrame);
1022 return;
1023}
1024
1025void GBCExpanderPass::Expand_PopShadowFrame() {
1026 rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
1027 return;
1028}
1029
1030void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
1031 irb_.StoreToObjectOffset(shadow_frame_,
1032 ShadowFrame::DexPCOffset(),
1033 dex_pc_value,
1034 kTBAAShadowFrame);
1035 return;
1036}
1037
1038bool GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
1039 // DexLang generates all alloca instruction in the first basic block of the
1040 // FUNC and also there's no any alloca instructions after the first non-alloca
1041 // instruction
1042
1043 llvm::BasicBlock::iterator first_non_alloca = func.front().begin();
1044 while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
1045 ++first_non_alloca;
1046 }
1047
1048 // Insert stack overflow check codes before first_non_alloca (i.e., after all
1049 // alloca instructions)
1050 return EmitStackOverflowCheck(&*first_non_alloca);
1051}
1052
TDYa1275e869b62012-07-25 00:45:39 -07001053// ==== High-level intrinsic expander ==========================================
1054
TDYa127a1b21852012-07-23 03:20:39 -07001055llvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
1056 llvm::Value* src2_value,
1057 bool gt_bias) {
1058 llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
1059 llvm::Value* cmp_lt;
1060
1061 if (gt_bias) {
1062 cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
1063 } else {
1064 cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
1065 }
1066
1067 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1068}
1069
1070llvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
1071 llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
1072 llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
1073
1074 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1075}
1076
1077llvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
1078 llvm::Value* cmp_lt) {
1079
1080 llvm::Constant* zero = irb_.getJInt(0);
1081 llvm::Constant* pos1 = irb_.getJInt(1);
1082 llvm::Constant* neg1 = irb_.getJInt(-1);
1083
1084 llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
1085 llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
1086
1087 return result_eq;
1088}
1089
Logan Chien75e4b602012-07-23 14:24:12 -07001090llvm::Value* GBCExpanderPass::Expand_IntegerShift(llvm::Value* src1_value,
1091 llvm::Value* src2_value,
1092 IntegerShiftKind kind,
1093 JType op_jty) {
1094 DCHECK(op_jty == kInt || op_jty == kLong);
1095
1096 // Mask and zero-extend RHS properly
1097 if (op_jty == kInt) {
1098 src2_value = irb_.CreateAnd(src2_value, 0x1f);
1099 } else {
1100 llvm::Value* masked_src2_value = irb_.CreateAnd(src2_value, 0x3f);
1101 src2_value = irb_.CreateZExt(masked_src2_value, irb_.getJLongTy());
1102 }
1103
1104 // Create integer shift llvm instruction
1105 switch (kind) {
1106 case kIntegerSHL:
1107 return irb_.CreateShl(src1_value, src2_value);
1108
1109 case kIntegerSHR:
1110 return irb_.CreateAShr(src1_value, src2_value);
1111
1112 case kIntegerUSHR:
1113 return irb_.CreateLShr(src1_value, src2_value);
1114
1115 default:
1116 LOG(FATAL) << "Unknown integer shift kind: " << kind;
1117 return NULL;
1118 }
1119}
1120
TDYa1275e869b62012-07-25 00:45:39 -07001121llvm::Value* GBCExpanderPass::Expand_HLIGet(llvm::CallInst& call_inst,
1122 JType field_jty) {
1123 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1124
1125 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1126 llvm::Value* object_addr = call_inst.getArgOperand(1);
1127 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(2));
1128
1129 // TODO: opt_flags
1130 EmitGuard_NullPointerException(dex_pc, object_addr);
1131
1132 llvm::Value* field_value;
1133
1134 int field_offset;
1135 bool is_volatile;
1136 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1137 field_idx, oat_compilation_unit_, field_offset, is_volatile, false);
1138
1139 if (!is_fast_path) {
1140 llvm::Function* runtime_func;
1141
1142 if (field_jty == kObject) {
1143 runtime_func = irb_.GetRuntime(runtime_support::GetObjectInstance);
1144 } else if (field_jty == kLong || field_jty == kDouble) {
1145 runtime_func = irb_.GetRuntime(runtime_support::Get64Instance);
1146 } else {
1147 runtime_func = irb_.GetRuntime(runtime_support::Get32Instance);
1148 }
1149
1150 llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
1151
1152 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1153
1154 EmitUpdateDexPC(dex_pc);
1155
1156 field_value = irb_.CreateCall3(runtime_func, field_idx_value,
1157 method_object_addr, object_addr);
1158
1159 EmitGuard_ExceptionLandingPad(dex_pc);
1160
1161 } else {
1162 DCHECK_GE(field_offset, 0);
1163
1164 llvm::PointerType* field_type =
1165 irb_.getJType(field_jty, kField)->getPointerTo();
1166
1167 llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset);
1168
1169 llvm::Value* field_addr =
1170 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1171
1172 // TODO: Check is_volatile. We need to generate atomic load instruction
1173 // when is_volatile is true.
1174 field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
1175 }
1176
1177 if (field_jty == kFloat || field_jty == kDouble) {
1178 field_value = irb_.CreateBitCast(field_value, irb_.getJType(field_jty, kReg));
1179 }
1180
1181 return field_value;
1182}
1183
1184void GBCExpanderPass::Expand_HLIPut(llvm::CallInst& call_inst,
1185 JType field_jty) {
1186 ScopedExpandToBasicBlock eb(irb_, &call_inst);
1187
1188 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1189 llvm::Value* object_addr = call_inst.getArgOperand(1);
1190 llvm::Value* new_value = call_inst.getArgOperand(2);
1191 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(3));
1192
1193 if (field_jty == kFloat || field_jty == kDouble) {
1194 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty, kReg));
1195 }
1196
1197 // TODO: opt_flags
1198 EmitGuard_NullPointerException(dex_pc, object_addr);
1199
1200 int field_offset;
1201 bool is_volatile;
1202 bool is_fast_path = compiler_->ComputeInstanceFieldInfo(
1203 field_idx, oat_compilation_unit_, field_offset, is_volatile, true);
1204
1205 if (!is_fast_path) {
1206 llvm::Function* runtime_func;
1207
1208 if (field_jty == kObject) {
1209 runtime_func = irb_.GetRuntime(runtime_support::SetObjectInstance);
1210 } else if (field_jty == kLong || field_jty == kDouble) {
1211 runtime_func = irb_.GetRuntime(runtime_support::Set64Instance);
1212 } else {
1213 runtime_func = irb_.GetRuntime(runtime_support::Set32Instance);
1214 }
1215
1216 llvm::Value* field_idx_value = irb_.getInt32(field_idx);
1217
1218 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1219
1220 EmitUpdateDexPC(dex_pc);
1221
1222 irb_.CreateCall4(runtime_func, field_idx_value,
1223 method_object_addr, object_addr, new_value);
1224
1225 EmitGuard_ExceptionLandingPad(dex_pc);
1226
1227 } else {
1228 DCHECK_GE(field_offset, 0);
1229
1230 llvm::PointerType* field_type =
1231 irb_.getJType(field_jty, kField)->getPointerTo();
1232
1233 llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset);
1234
1235 llvm::Value* field_addr =
1236 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1237
1238 // TODO: Check is_volatile. We need to generate atomic store instruction
1239 // when is_volatile is true.
1240 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
1241
1242 if (field_jty == kObject) { // If put an object, mark the GC card table.
1243 EmitMarkGCCard(new_value, object_addr);
1244 }
1245 }
1246
1247 return;
1248}
1249
1250void GBCExpanderPass::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
1251 // Using runtime support, let the target can override by InlineAssembly.
1252 irb_.Runtime().EmitMarkGCCard(value, target_addr);
1253}
1254
1255void GBCExpanderPass::EmitUpdateDexPC(uint32_t dex_pc) {
1256 irb_.StoreToObjectOffset(shadow_frame_,
1257 ShadowFrame::DexPCOffset(),
1258 irb_.getInt32(dex_pc),
1259 kTBAAShadowFrame);
1260}
1261
1262void GBCExpanderPass::EmitGuard_DivZeroException(uint32_t dex_pc,
1263 llvm::Value* denominator,
1264 JType op_jty) {
1265 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
1266
1267 llvm::Constant* zero = irb_.getJZero(op_jty);
1268
1269 llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
1270
1271 llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
1272
1273 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
1274
1275 irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
1276
1277 irb_.SetInsertPoint(block_exception);
1278 EmitUpdateDexPC(dex_pc);
1279 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowDivZeroException));
1280 EmitBranchExceptionLandingPad(dex_pc);
1281
1282 irb_.SetInsertPoint(block_continue);
1283}
1284
1285void GBCExpanderPass::EmitGuard_NullPointerException(uint32_t dex_pc,
1286 llvm::Value* object) {
1287 llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
1288
1289 llvm::BasicBlock* block_exception =
1290 CreateBasicBlockWithDexPC(dex_pc, "nullp");
1291
1292 llvm::BasicBlock* block_continue =
1293 CreateBasicBlockWithDexPC(dex_pc, "cont");
1294
1295 irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
1296
1297 irb_.SetInsertPoint(block_exception);
1298 EmitUpdateDexPC(dex_pc);
1299 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowNullPointerException),
1300 irb_.getInt32(dex_pc));
1301 EmitBranchExceptionLandingPad(dex_pc);
1302
1303 irb_.SetInsertPoint(block_continue);
1304}
1305
1306void
1307GBCExpanderPass::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
1308 llvm::Value* array,
1309 llvm::Value* index) {
1310 llvm::Value* array_len = EmitLoadArrayLength(array);
1311
1312 llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
1313
1314 llvm::BasicBlock* block_exception =
1315 CreateBasicBlockWithDexPC(dex_pc, "overflow");
1316
1317 llvm::BasicBlock* block_continue =
1318 CreateBasicBlockWithDexPC(dex_pc, "cont");
1319
1320 irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
1321
1322 irb_.SetInsertPoint(block_exception);
1323
1324 EmitUpdateDexPC(dex_pc);
1325 irb_.CreateCall2(irb_.GetRuntime(runtime_support::ThrowIndexOutOfBounds), index, array_len);
1326 EmitBranchExceptionLandingPad(dex_pc);
1327
1328 irb_.SetInsertPoint(block_continue);
1329}
1330
1331void GBCExpanderPass::EmitGuard_ArrayException(uint32_t dex_pc,
1332 llvm::Value* array,
1333 llvm::Value* index) {
1334 EmitGuard_NullPointerException(dex_pc, array);
1335 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array, index);
1336}
1337
1338llvm::FunctionType* GBCExpanderPass::GetFunctionType(uint32_t method_idx,
1339 bool is_static) {
1340 // Get method signature
1341 DexFile::MethodId const& method_id = dex_file_->GetMethodId(method_idx);
1342
1343 uint32_t shorty_size;
1344 const char* shorty = dex_file_->GetMethodShorty(method_id, &shorty_size);
1345 CHECK_GE(shorty_size, 1u);
1346
1347 // Get return type
1348 llvm::Type* ret_type = irb_.getJType(shorty[0], kAccurate);
1349
1350 // Get argument type
1351 std::vector<llvm::Type*> args_type;
1352
1353 args_type.push_back(irb_.getJObjectTy()); // method object pointer
1354
1355 if (!is_static) {
1356 args_type.push_back(irb_.getJType('L', kAccurate)); // "this" object pointer
1357 }
1358
1359 for (uint32_t i = 1; i < shorty_size; ++i) {
1360 args_type.push_back(irb_.getJType(shorty[i], kAccurate));
1361 }
1362
1363 return llvm::FunctionType::get(ret_type, args_type, false);
1364}
1365
1366
1367llvm::BasicBlock* GBCExpanderPass::
1368CreateBasicBlockWithDexPC(uint32_t dex_pc, const char* postfix) {
1369 std::string name;
1370
1371#if !defined(NDEBUG)
1372 StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
1373#endif
1374
1375 return llvm::BasicBlock::Create(context_, name, func_);
1376}
1377
1378llvm::BasicBlock* GBCExpanderPass::GetBasicBlock(uint32_t dex_pc) {
1379 DCHECK(dex_pc < code_item_->insns_size_in_code_units_);
1380
1381 return basic_blocks_[dex_pc];
1382}
1383
1384int32_t GBCExpanderPass::GetTryItemOffset(uint32_t dex_pc) {
1385 int32_t min = 0;
1386 int32_t max = code_item_->tries_size_ - 1;
1387
1388 while (min <= max) {
1389 int32_t mid = min + (max - min) / 2;
1390
1391 const DexFile::TryItem* ti = DexFile::GetTryItems(*code_item_, mid);
1392 uint32_t start = ti->start_addr_;
1393 uint32_t end = start + ti->insn_count_;
1394
1395 if (dex_pc < start) {
1396 max = mid - 1;
1397 } else if (dex_pc >= end) {
1398 min = mid + 1;
1399 } else {
1400 return mid; // found
1401 }
1402 }
1403
1404 return -1; // not found
1405}
1406
1407llvm::BasicBlock* GBCExpanderPass::GetLandingPadBasicBlock(uint32_t dex_pc) {
1408 // Find the try item for this address in this method
1409 int32_t ti_offset = GetTryItemOffset(dex_pc);
1410
1411 if (ti_offset == -1) {
1412 return NULL; // No landing pad is available for this address.
1413 }
1414
1415 // Check for the existing landing pad basic block
1416 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
1417 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
1418
1419 if (block_lpad) {
1420 // We have generated landing pad for this try item already. Return the
1421 // same basic block.
1422 return block_lpad;
1423 }
1424
1425 // Get try item from code item
1426 const DexFile::TryItem* ti = DexFile::GetTryItems(*code_item_, ti_offset);
1427
1428 std::string lpadname;
1429
1430#if !defined(NDEBUG)
1431 StringAppendF(&lpadname, "lpad%d_%04x_to_%04x", ti_offset, ti->start_addr_, ti->handler_off_);
1432#endif
1433
1434 // Create landing pad basic block
1435 block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
1436
1437 // Change IRBuilder insert point
1438 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
1439 irb_.SetInsertPoint(block_lpad);
1440
1441 // Find catch block with matching type
1442 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1443
1444 llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
1445
1446 llvm::Value* catch_handler_index_value =
1447 irb_.CreateCall2(irb_.GetRuntime(runtime_support::FindCatchBlock),
1448 method_object_addr, ti_offset_value);
1449
1450 // Switch instruction (Go to unwind basic block by default)
1451 llvm::SwitchInst* sw =
1452 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
1453
1454 // Cases with matched catch block
1455 CatchHandlerIterator iter(*code_item_, ti->start_addr_);
1456
1457 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
1458 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
1459 }
1460
1461 // Restore the orignal insert point for IRBuilder
1462 irb_.restoreIP(irb_ip_original);
1463
1464 // Cache this landing pad
1465 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
1466 basic_block_landing_pads_[ti_offset] = block_lpad;
1467
1468 return block_lpad;
1469}
1470
1471llvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() {
1472 // Check the existing unwinding baisc block block
1473 if (basic_block_unwind_ != NULL) {
1474 return basic_block_unwind_;
1475 }
1476
1477 // Create new basic block for unwinding
1478 basic_block_unwind_ =
1479 llvm::BasicBlock::Create(context_, "exception_unwind", func_);
1480
1481 // Change IRBuilder insert point
1482 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
1483 irb_.SetInsertPoint(basic_block_unwind_);
1484
1485 // Pop the shadow frame
1486 Expand_PopShadowFrame();
1487
1488 // Emit the code to return default value (zero) for the given return type.
1489 char ret_shorty = oat_compilation_unit_->GetShorty()[0];
1490 if (ret_shorty == 'V') {
1491 irb_.CreateRetVoid();
1492 } else {
1493 irb_.CreateRet(irb_.getJZero(ret_shorty));
1494 }
1495
1496 // Restore the orignal insert point for IRBuilder
1497 irb_.restoreIP(irb_ip_original);
1498
1499 return basic_block_unwind_;
1500}
1501
1502void GBCExpanderPass::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
1503 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
1504 irb_.CreateBr(lpad);
1505 } else {
1506 irb_.CreateBr(GetUnwindBasicBlock());
1507 }
1508}
1509
1510void GBCExpanderPass::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
1511 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
1512
1513 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
1514
1515 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
1516 irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
1517 } else {
1518 irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
1519 }
1520
1521 irb_.SetInsertPoint(block_cont);
1522}
1523
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001524llvm::Value*
1525GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
1526 llvm::CallInst& call_inst) {
1527 switch (intr_id) {
1528 //==- Thread -----------------------------------------------------------==//
1529 case IntrinsicHelper::GetCurrentThread: {
TDYa127b672d1e2012-06-28 21:21:45 -07001530 return irb_.Runtime().EmitGetCurrentThread();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001531 }
Logan Chiend54a23d2012-07-24 11:19:23 -07001532 case IntrinsicHelper::TestSuspend:
Logan Chien75e4b602012-07-23 14:24:12 -07001533 case IntrinsicHelper::CheckSuspend: {
Logan Chiend54a23d2012-07-24 11:19:23 -07001534 Expand_TestSuspend(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07001535 return NULL;
1536 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001537 case IntrinsicHelper::MarkGCCard: {
TDYa1279a129452012-07-19 03:10:08 -07001538 Expand_MarkGCCard(call_inst);
1539 return NULL;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001540 }
Logan Chien75e4b602012-07-23 14:24:12 -07001541
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001542 //==- Exception --------------------------------------------------------==//
1543 case IntrinsicHelper::ThrowException: {
1544 return ExpandToRuntime(runtime_support::ThrowException, call_inst);
1545 }
1546 case IntrinsicHelper::GetException: {
1547 return Expand_GetException();
1548 }
1549 case IntrinsicHelper::IsExceptionPending: {
1550 return irb_.Runtime().EmitIsExceptionPending();
1551 }
1552 case IntrinsicHelper::FindCatchBlock: {
1553 return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
1554 }
1555 case IntrinsicHelper::ThrowDivZeroException: {
1556 return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
1557 }
1558 case IntrinsicHelper::ThrowNullPointerException: {
1559 return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
1560 }
1561 case IntrinsicHelper::ThrowIndexOutOfBounds: {
1562 return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
1563 }
Logan Chien75e4b602012-07-23 14:24:12 -07001564
1565 //==- Const String -----------------------------------------------------==//
1566 case IntrinsicHelper::ConstString: {
1567 UNIMPLEMENTED(FATAL);
1568 return NULL;
1569 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001570 case IntrinsicHelper::LoadStringFromDexCache: {
1571 return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
1572 }
1573 case IntrinsicHelper::ResolveString: {
1574 return ExpandToRuntime(runtime_support::ResolveString, call_inst);
1575 }
Logan Chien75e4b602012-07-23 14:24:12 -07001576
1577 //==- Const Class ------------------------------------------------------==//
1578 case IntrinsicHelper::ConstClass: {
1579 UNIMPLEMENTED(FATAL);
1580 return NULL;
1581 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001582 case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
1583 return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
1584 }
1585 case IntrinsicHelper::LoadTypeFromDexCache: {
1586 return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
1587 }
1588 case IntrinsicHelper::InitializeType: {
1589 return ExpandToRuntime(runtime_support::InitializeType, call_inst);
1590 }
Logan Chien75e4b602012-07-23 14:24:12 -07001591
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001592 //==- Lock -------------------------------------------------------------==//
1593 case IntrinsicHelper::LockObject: {
1594 Expand_LockObject(call_inst.getArgOperand(0));
1595 return NULL;
1596 }
1597 case IntrinsicHelper::UnlockObject: {
1598 Expand_UnlockObject(call_inst.getArgOperand(0));
1599 return NULL;
1600 }
Logan Chien75e4b602012-07-23 14:24:12 -07001601
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001602 //==- Cast -------------------------------------------------------------==//
1603 case IntrinsicHelper::CheckCast: {
1604 return ExpandToRuntime(runtime_support::CheckCast, call_inst);
1605 }
Logan Chien75e4b602012-07-23 14:24:12 -07001606 case IntrinsicHelper::HLCheckCast: {
1607 UNIMPLEMENTED(FATAL);
1608 return NULL;
1609 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001610 case IntrinsicHelper::IsAssignable: {
1611 return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
1612 }
Logan Chien75e4b602012-07-23 14:24:12 -07001613
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001614 //==- Alloc ------------------------------------------------------------==//
1615 case IntrinsicHelper::AllocObject: {
1616 return ExpandToRuntime(runtime_support::AllocObject, call_inst);
1617 }
1618 case IntrinsicHelper::AllocObjectWithAccessCheck: {
1619 return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
1620 }
Logan Chien75e4b602012-07-23 14:24:12 -07001621
1622 //==- Instance ---------------------------------------------------------==//
1623 case IntrinsicHelper::NewInstance: {
1624 UNIMPLEMENTED(FATAL);
1625 return NULL;
1626 }
1627 case IntrinsicHelper::InstanceOf: {
1628 UNIMPLEMENTED(FATAL);
1629 return NULL;
1630 }
1631
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001632 //==- Array ------------------------------------------------------------==//
Logan Chien75e4b602012-07-23 14:24:12 -07001633 case IntrinsicHelper::NewArray: {
1634 UNIMPLEMENTED(FATAL);
1635 return NULL;
1636 }
1637 case IntrinsicHelper::OptArrayLength: {
1638 UNIMPLEMENTED(FATAL);
1639 return NULL;
1640 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001641 case IntrinsicHelper::ArrayLength: {
1642 return EmitLoadArrayLength(call_inst.getArgOperand(0));
1643 }
1644 case IntrinsicHelper::AllocArray: {
1645 return ExpandToRuntime(runtime_support::AllocArray, call_inst);
1646 }
1647 case IntrinsicHelper::AllocArrayWithAccessCheck: {
1648 return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
1649 call_inst);
1650 }
1651 case IntrinsicHelper::CheckAndAllocArray: {
1652 return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
1653 }
1654 case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
1655 return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
1656 call_inst);
1657 }
1658 case IntrinsicHelper::ArrayGet: {
1659 return Expand_ArrayGet(call_inst.getArgOperand(0),
1660 call_inst.getArgOperand(1),
1661 kInt);
1662 }
1663 case IntrinsicHelper::ArrayGetWide: {
1664 return Expand_ArrayGet(call_inst.getArgOperand(0),
1665 call_inst.getArgOperand(1),
1666 kLong);
1667 }
1668 case IntrinsicHelper::ArrayGetObject: {
1669 return Expand_ArrayGet(call_inst.getArgOperand(0),
1670 call_inst.getArgOperand(1),
1671 kObject);
1672 }
1673 case IntrinsicHelper::ArrayGetBoolean: {
1674 return Expand_ArrayGet(call_inst.getArgOperand(0),
1675 call_inst.getArgOperand(1),
1676 kBoolean);
1677 }
1678 case IntrinsicHelper::ArrayGetByte: {
1679 return Expand_ArrayGet(call_inst.getArgOperand(0),
1680 call_inst.getArgOperand(1),
1681 kByte);
1682 }
1683 case IntrinsicHelper::ArrayGetChar: {
1684 return Expand_ArrayGet(call_inst.getArgOperand(0),
1685 call_inst.getArgOperand(1),
1686 kChar);
1687 }
1688 case IntrinsicHelper::ArrayGetShort: {
1689 return Expand_ArrayGet(call_inst.getArgOperand(0),
1690 call_inst.getArgOperand(1),
1691 kShort);
1692 }
1693 case IntrinsicHelper::ArrayPut: {
1694 Expand_ArrayPut(call_inst.getArgOperand(0),
1695 call_inst.getArgOperand(1),
1696 call_inst.getArgOperand(2),
1697 kInt);
1698 return NULL;
1699 }
1700 case IntrinsicHelper::ArrayPutWide: {
1701 Expand_ArrayPut(call_inst.getArgOperand(0),
1702 call_inst.getArgOperand(1),
1703 call_inst.getArgOperand(2),
1704 kLong);
1705 return NULL;
1706 }
1707 case IntrinsicHelper::ArrayPutObject: {
1708 Expand_ArrayPut(call_inst.getArgOperand(0),
1709 call_inst.getArgOperand(1),
1710 call_inst.getArgOperand(2),
1711 kObject);
1712 return NULL;
1713 }
1714 case IntrinsicHelper::ArrayPutBoolean: {
1715 Expand_ArrayPut(call_inst.getArgOperand(0),
1716 call_inst.getArgOperand(1),
1717 call_inst.getArgOperand(2),
1718 kBoolean);
1719 return NULL;
1720 }
1721 case IntrinsicHelper::ArrayPutByte: {
1722 Expand_ArrayPut(call_inst.getArgOperand(0),
1723 call_inst.getArgOperand(1),
1724 call_inst.getArgOperand(2),
1725 kByte);
1726 return NULL;
1727 }
1728 case IntrinsicHelper::ArrayPutChar: {
1729 Expand_ArrayPut(call_inst.getArgOperand(0),
1730 call_inst.getArgOperand(1),
1731 call_inst.getArgOperand(2),
1732 kChar);
1733 return NULL;
1734 }
1735 case IntrinsicHelper::ArrayPutShort: {
1736 Expand_ArrayPut(call_inst.getArgOperand(0),
1737 call_inst.getArgOperand(1),
1738 call_inst.getArgOperand(2),
1739 kShort);
1740 return NULL;
1741 }
1742 case IntrinsicHelper::CheckPutArrayElement: {
1743 return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
1744 }
1745 case IntrinsicHelper::FilledNewArray: {
1746 Expand_FilledNewArray(call_inst);
1747 return NULL;
1748 }
1749 case IntrinsicHelper::FillArrayData: {
1750 return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
1751 }
Logan Chien75e4b602012-07-23 14:24:12 -07001752 case IntrinsicHelper::HLFillArrayData: {
1753 UNIMPLEMENTED(FATAL);
1754 return NULL;
1755 }
1756 case IntrinsicHelper::HLFilledNewArray: {
1757 UNIMPLEMENTED(FATAL);
1758 return NULL;
1759 }
1760
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001761 //==- Instance Field ---------------------------------------------------==//
1762 case IntrinsicHelper::InstanceFieldGet:
1763 case IntrinsicHelper::InstanceFieldGetBoolean:
1764 case IntrinsicHelper::InstanceFieldGetByte:
1765 case IntrinsicHelper::InstanceFieldGetChar:
1766 case IntrinsicHelper::InstanceFieldGetShort: {
1767 return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
1768 }
1769 case IntrinsicHelper::InstanceFieldGetWide: {
1770 return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
1771 }
1772 case IntrinsicHelper::InstanceFieldGetObject: {
1773 return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
1774 }
1775 case IntrinsicHelper::InstanceFieldGetFast: {
1776 return Expand_IGetFast(call_inst.getArgOperand(0),
1777 call_inst.getArgOperand(1),
1778 call_inst.getArgOperand(2),
1779 kInt);
1780 }
1781 case IntrinsicHelper::InstanceFieldGetWideFast: {
1782 return Expand_IGetFast(call_inst.getArgOperand(0),
1783 call_inst.getArgOperand(1),
1784 call_inst.getArgOperand(2),
1785 kLong);
1786 }
1787 case IntrinsicHelper::InstanceFieldGetObjectFast: {
1788 return Expand_IGetFast(call_inst.getArgOperand(0),
1789 call_inst.getArgOperand(1),
1790 call_inst.getArgOperand(2),
1791 kObject);
1792 }
1793 case IntrinsicHelper::InstanceFieldGetBooleanFast: {
1794 return Expand_IGetFast(call_inst.getArgOperand(0),
1795 call_inst.getArgOperand(1),
1796 call_inst.getArgOperand(2),
1797 kBoolean);
1798 }
1799 case IntrinsicHelper::InstanceFieldGetByteFast: {
1800 return Expand_IGetFast(call_inst.getArgOperand(0),
1801 call_inst.getArgOperand(1),
1802 call_inst.getArgOperand(2),
1803 kByte);
1804 }
1805 case IntrinsicHelper::InstanceFieldGetCharFast: {
1806 return Expand_IGetFast(call_inst.getArgOperand(0),
1807 call_inst.getArgOperand(1),
1808 call_inst.getArgOperand(2),
1809 kChar);
1810 }
1811 case IntrinsicHelper::InstanceFieldGetShortFast: {
1812 return Expand_IGetFast(call_inst.getArgOperand(0),
1813 call_inst.getArgOperand(1),
1814 call_inst.getArgOperand(2),
1815 kShort);
1816 }
1817 case IntrinsicHelper::InstanceFieldPut:
1818 case IntrinsicHelper::InstanceFieldPutBoolean:
1819 case IntrinsicHelper::InstanceFieldPutByte:
1820 case IntrinsicHelper::InstanceFieldPutChar:
1821 case IntrinsicHelper::InstanceFieldPutShort: {
1822 return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
1823 }
1824 case IntrinsicHelper::InstanceFieldPutWide: {
1825 return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
1826 }
1827 case IntrinsicHelper::InstanceFieldPutObject: {
1828 return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
1829 }
1830 case IntrinsicHelper::InstanceFieldPutFast: {
1831 Expand_IPutFast(call_inst.getArgOperand(0),
1832 call_inst.getArgOperand(1),
1833 call_inst.getArgOperand(2),
1834 call_inst.getArgOperand(3),
1835 kInt);
1836 return NULL;
1837 }
1838 case IntrinsicHelper::InstanceFieldPutWideFast: {
1839 Expand_IPutFast(call_inst.getArgOperand(0),
1840 call_inst.getArgOperand(1),
1841 call_inst.getArgOperand(2),
1842 call_inst.getArgOperand(3),
1843 kLong);
1844 return NULL;
1845 }
1846 case IntrinsicHelper::InstanceFieldPutObjectFast: {
1847 Expand_IPutFast(call_inst.getArgOperand(0),
1848 call_inst.getArgOperand(1),
1849 call_inst.getArgOperand(2),
1850 call_inst.getArgOperand(3),
1851 kObject);
1852 return NULL;
1853 }
1854 case IntrinsicHelper::InstanceFieldPutBooleanFast: {
1855 Expand_IPutFast(call_inst.getArgOperand(0),
1856 call_inst.getArgOperand(1),
1857 call_inst.getArgOperand(2),
1858 call_inst.getArgOperand(3),
1859 kBoolean);
1860 return NULL;
1861 }
1862 case IntrinsicHelper::InstanceFieldPutByteFast: {
1863 Expand_IPutFast(call_inst.getArgOperand(0),
1864 call_inst.getArgOperand(1),
1865 call_inst.getArgOperand(2),
1866 call_inst.getArgOperand(3),
1867 kByte);
1868 return NULL;
1869 }
1870 case IntrinsicHelper::InstanceFieldPutCharFast: {
1871 Expand_IPutFast(call_inst.getArgOperand(0),
1872 call_inst.getArgOperand(1),
1873 call_inst.getArgOperand(2),
1874 call_inst.getArgOperand(3),
1875 kChar);
1876 return NULL;
1877 }
1878 case IntrinsicHelper::InstanceFieldPutShortFast: {
1879 Expand_IPutFast(call_inst.getArgOperand(0),
1880 call_inst.getArgOperand(1),
1881 call_inst.getArgOperand(2),
1882 call_inst.getArgOperand(3),
1883 kShort);
1884 return NULL;
1885 }
Logan Chien75e4b602012-07-23 14:24:12 -07001886
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001887 //==- Static Field -----------------------------------------------------==//
1888 case IntrinsicHelper::StaticFieldGet:
1889 case IntrinsicHelper::StaticFieldGetBoolean:
1890 case IntrinsicHelper::StaticFieldGetByte:
1891 case IntrinsicHelper::StaticFieldGetChar:
1892 case IntrinsicHelper::StaticFieldGetShort: {
1893 return ExpandToRuntime(runtime_support::Get32Static, call_inst);
1894 }
1895 case IntrinsicHelper::StaticFieldGetWide: {
1896 return ExpandToRuntime(runtime_support::Get64Static, call_inst);
1897 }
1898 case IntrinsicHelper::StaticFieldGetObject: {
1899 return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
1900 }
1901 case IntrinsicHelper::StaticFieldGetFast: {
1902 return Expand_SGetFast(call_inst.getArgOperand(0),
1903 call_inst.getArgOperand(1),
1904 call_inst.getArgOperand(2),
1905 kInt);
1906 }
1907 case IntrinsicHelper::StaticFieldGetWideFast: {
1908 return Expand_SGetFast(call_inst.getArgOperand(0),
1909 call_inst.getArgOperand(1),
1910 call_inst.getArgOperand(2),
1911 kLong);
1912 }
1913 case IntrinsicHelper::StaticFieldGetObjectFast: {
1914 return Expand_SGetFast(call_inst.getArgOperand(0),
1915 call_inst.getArgOperand(1),
1916 call_inst.getArgOperand(2),
1917 kObject);
1918 }
1919 case IntrinsicHelper::StaticFieldGetBooleanFast: {
1920 return Expand_SGetFast(call_inst.getArgOperand(0),
1921 call_inst.getArgOperand(1),
1922 call_inst.getArgOperand(2),
1923 kBoolean);
1924 }
1925 case IntrinsicHelper::StaticFieldGetByteFast: {
1926 return Expand_SGetFast(call_inst.getArgOperand(0),
1927 call_inst.getArgOperand(1),
1928 call_inst.getArgOperand(2),
1929 kByte);
1930 }
1931 case IntrinsicHelper::StaticFieldGetCharFast: {
1932 return Expand_SGetFast(call_inst.getArgOperand(0),
1933 call_inst.getArgOperand(1),
1934 call_inst.getArgOperand(2),
1935 kChar);
1936 }
1937 case IntrinsicHelper::StaticFieldGetShortFast: {
1938 return Expand_SGetFast(call_inst.getArgOperand(0),
1939 call_inst.getArgOperand(1),
1940 call_inst.getArgOperand(2),
1941 kShort);
1942 }
1943 case IntrinsicHelper::StaticFieldPut:
1944 case IntrinsicHelper::StaticFieldPutBoolean:
1945 case IntrinsicHelper::StaticFieldPutByte:
1946 case IntrinsicHelper::StaticFieldPutChar:
1947 case IntrinsicHelper::StaticFieldPutShort: {
1948 return ExpandToRuntime(runtime_support::Set32Static, call_inst);
1949 }
1950 case IntrinsicHelper::StaticFieldPutWide: {
1951 return ExpandToRuntime(runtime_support::Set64Static, call_inst);
1952 }
1953 case IntrinsicHelper::StaticFieldPutObject: {
1954 return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
1955 }
1956 case IntrinsicHelper::StaticFieldPutFast: {
1957 Expand_SPutFast(call_inst.getArgOperand(0),
1958 call_inst.getArgOperand(1),
1959 call_inst.getArgOperand(2),
1960 call_inst.getArgOperand(3),
1961 kInt);
1962 return NULL;
1963 }
1964 case IntrinsicHelper::StaticFieldPutWideFast: {
1965 Expand_SPutFast(call_inst.getArgOperand(0),
1966 call_inst.getArgOperand(1),
1967 call_inst.getArgOperand(2),
1968 call_inst.getArgOperand(3),
1969 kLong);
1970 return NULL;
1971 }
1972 case IntrinsicHelper::StaticFieldPutObjectFast: {
1973 Expand_SPutFast(call_inst.getArgOperand(0),
1974 call_inst.getArgOperand(1),
1975 call_inst.getArgOperand(2),
1976 call_inst.getArgOperand(3),
1977 kObject);
1978 return NULL;
1979 }
1980 case IntrinsicHelper::StaticFieldPutBooleanFast: {
1981 Expand_SPutFast(call_inst.getArgOperand(0),
1982 call_inst.getArgOperand(1),
1983 call_inst.getArgOperand(2),
1984 call_inst.getArgOperand(3),
1985 kBoolean);
1986 return NULL;
1987 }
1988 case IntrinsicHelper::StaticFieldPutByteFast: {
1989 Expand_SPutFast(call_inst.getArgOperand(0),
1990 call_inst.getArgOperand(1),
1991 call_inst.getArgOperand(2),
1992 call_inst.getArgOperand(3),
1993 kByte);
1994 return NULL;
1995 }
1996 case IntrinsicHelper::StaticFieldPutCharFast: {
1997 Expand_SPutFast(call_inst.getArgOperand(0),
1998 call_inst.getArgOperand(1),
1999 call_inst.getArgOperand(2),
2000 call_inst.getArgOperand(3),
2001 kChar);
2002 return NULL;
2003 }
2004 case IntrinsicHelper::StaticFieldPutShortFast: {
2005 Expand_SPutFast(call_inst.getArgOperand(0),
2006 call_inst.getArgOperand(1),
2007 call_inst.getArgOperand(2),
2008 call_inst.getArgOperand(3),
2009 kShort);
2010 return NULL;
2011 }
2012 case IntrinsicHelper::LoadDeclaringClassSSB: {
2013 return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
2014 }
2015 case IntrinsicHelper::LoadClassSSBFromDexCache: {
2016 return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
2017 }
2018 case IntrinsicHelper::InitializeAndLoadClassSSB: {
2019 return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
2020 }
Logan Chien75e4b602012-07-23 14:24:12 -07002021
2022 //==- High-level Array -------------------------------------------------==//
2023 case IntrinsicHelper::HLArrayGet: {
2024 UNIMPLEMENTED(FATAL);
2025 return NULL;
2026 }
2027 case IntrinsicHelper::HLArrayGetBoolean: {
2028 UNIMPLEMENTED(FATAL);
2029 return NULL;
2030 }
2031 case IntrinsicHelper::HLArrayGetByte: {
2032 UNIMPLEMENTED(FATAL);
2033 return NULL;
2034 }
2035 case IntrinsicHelper::HLArrayGetChar: {
2036 UNIMPLEMENTED(FATAL);
2037 return NULL;
2038 }
2039 case IntrinsicHelper::HLArrayGetShort: {
2040 UNIMPLEMENTED(FATAL);
2041 return NULL;
2042 }
2043 case IntrinsicHelper::HLArrayGetFloat: {
2044 UNIMPLEMENTED(FATAL);
2045 return NULL;
2046 }
2047 case IntrinsicHelper::HLArrayGetWide: {
2048 UNIMPLEMENTED(FATAL);
2049 return NULL;
2050 }
2051 case IntrinsicHelper::HLArrayGetDouble: {
2052 UNIMPLEMENTED(FATAL);
2053 return NULL;
2054 }
2055 case IntrinsicHelper::HLArrayGetObject: {
2056 UNIMPLEMENTED(FATAL);
2057 return NULL;
2058 }
2059 case IntrinsicHelper::HLArrayPut: {
2060 UNIMPLEMENTED(FATAL);
2061 return NULL;
2062 }
2063 case IntrinsicHelper::HLArrayPutBoolean: {
2064 UNIMPLEMENTED(FATAL);
2065 return NULL;
2066 }
2067 case IntrinsicHelper::HLArrayPutByte: {
2068 UNIMPLEMENTED(FATAL);
2069 return NULL;
2070 }
2071 case IntrinsicHelper::HLArrayPutChar: {
2072 UNIMPLEMENTED(FATAL);
2073 return NULL;
2074 }
2075 case IntrinsicHelper::HLArrayPutShort: {
2076 UNIMPLEMENTED(FATAL);
2077 return NULL;
2078 }
2079 case IntrinsicHelper::HLArrayPutFloat: {
2080 UNIMPLEMENTED(FATAL);
2081 return NULL;
2082 }
2083 case IntrinsicHelper::HLArrayPutWide: {
2084 UNIMPLEMENTED(FATAL);
2085 return NULL;
2086 }
2087 case IntrinsicHelper::HLArrayPutDouble: {
2088 UNIMPLEMENTED(FATAL);
2089 return NULL;
2090 }
2091 case IntrinsicHelper::HLArrayPutObject: {
2092 UNIMPLEMENTED(FATAL);
2093 return NULL;
2094 }
2095
2096 //==- High-level Instance ----------------------------------------------==//
2097 case IntrinsicHelper::HLIGet: {
TDYa1275e869b62012-07-25 00:45:39 -07002098 return Expand_HLIGet(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07002099 }
2100 case IntrinsicHelper::HLIGetBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07002101 return Expand_HLIGet(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07002102 }
2103 case IntrinsicHelper::HLIGetByte: {
TDYa1275e869b62012-07-25 00:45:39 -07002104 return Expand_HLIGet(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07002105 }
2106 case IntrinsicHelper::HLIGetChar: {
TDYa1275e869b62012-07-25 00:45:39 -07002107 return Expand_HLIGet(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07002108 }
2109 case IntrinsicHelper::HLIGetShort: {
TDYa1275e869b62012-07-25 00:45:39 -07002110 return Expand_HLIGet(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07002111 }
2112 case IntrinsicHelper::HLIGetFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07002113 return Expand_HLIGet(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07002114 }
2115 case IntrinsicHelper::HLIGetWide: {
TDYa1275e869b62012-07-25 00:45:39 -07002116 return Expand_HLIGet(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07002117 }
2118 case IntrinsicHelper::HLIGetDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07002119 return Expand_HLIGet(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07002120 }
2121 case IntrinsicHelper::HLIGetObject: {
TDYa1275e869b62012-07-25 00:45:39 -07002122 return Expand_HLIGet(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07002123 }
2124 case IntrinsicHelper::HLIPut: {
TDYa1275e869b62012-07-25 00:45:39 -07002125 Expand_HLIPut(call_inst, kInt);
Logan Chien75e4b602012-07-23 14:24:12 -07002126 return NULL;
2127 }
2128 case IntrinsicHelper::HLIPutBoolean: {
TDYa1275e869b62012-07-25 00:45:39 -07002129 Expand_HLIPut(call_inst, kBoolean);
Logan Chien75e4b602012-07-23 14:24:12 -07002130 return NULL;
2131 }
2132 case IntrinsicHelper::HLIPutByte: {
TDYa1275e869b62012-07-25 00:45:39 -07002133 Expand_HLIPut(call_inst, kByte);
Logan Chien75e4b602012-07-23 14:24:12 -07002134 return NULL;
2135 }
2136 case IntrinsicHelper::HLIPutChar: {
TDYa1275e869b62012-07-25 00:45:39 -07002137 Expand_HLIPut(call_inst, kChar);
Logan Chien75e4b602012-07-23 14:24:12 -07002138 return NULL;
2139 }
2140 case IntrinsicHelper::HLIPutShort: {
TDYa1275e869b62012-07-25 00:45:39 -07002141 Expand_HLIPut(call_inst, kShort);
Logan Chien75e4b602012-07-23 14:24:12 -07002142 return NULL;
2143 }
2144 case IntrinsicHelper::HLIPutFloat: {
TDYa1275e869b62012-07-25 00:45:39 -07002145 Expand_HLIPut(call_inst, kFloat);
Logan Chien75e4b602012-07-23 14:24:12 -07002146 return NULL;
2147 }
2148 case IntrinsicHelper::HLIPutWide: {
TDYa1275e869b62012-07-25 00:45:39 -07002149 Expand_HLIPut(call_inst, kLong);
Logan Chien75e4b602012-07-23 14:24:12 -07002150 return NULL;
2151 }
2152 case IntrinsicHelper::HLIPutDouble: {
TDYa1275e869b62012-07-25 00:45:39 -07002153 Expand_HLIPut(call_inst, kDouble);
Logan Chien75e4b602012-07-23 14:24:12 -07002154 return NULL;
2155 }
2156 case IntrinsicHelper::HLIPutObject: {
TDYa1275e869b62012-07-25 00:45:39 -07002157 Expand_HLIPut(call_inst, kObject);
Logan Chien75e4b602012-07-23 14:24:12 -07002158 return NULL;
2159 }
2160
2161 //==- High-level Invoke ------------------------------------------------==//
2162 case IntrinsicHelper::HLInvokeVoid: {
2163 UNIMPLEMENTED(FATAL);
2164 return NULL;
2165 }
2166 case IntrinsicHelper::HLInvokeObj: {
2167 UNIMPLEMENTED(FATAL);
2168 return NULL;
2169 }
2170 case IntrinsicHelper::HLInvokeInt: {
2171 UNIMPLEMENTED(FATAL);
2172 return NULL;
2173 }
2174 case IntrinsicHelper::HLInvokeFloat: {
2175 UNIMPLEMENTED(FATAL);
2176 return NULL;
2177 }
2178 case IntrinsicHelper::HLInvokeLong: {
2179 UNIMPLEMENTED(FATAL);
2180 return NULL;
2181 }
2182 case IntrinsicHelper::HLInvokeDouble: {
2183 UNIMPLEMENTED(FATAL);
2184 return NULL;
2185 }
2186
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002187 //==- Invoke -----------------------------------------------------------==//
2188 case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
2189 return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
2190 }
2191 case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
2192 return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
2193 }
2194 case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
2195 return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
2196 }
2197 case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
2198 return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
2199 }
2200 case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
2201 return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
2202 }
2203 case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
2204 return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
2205 }
2206 case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
2207 return Expand_GetVirtualCalleeMethodObjAddrFast(
2208 call_inst.getArgOperand(0), call_inst.getArgOperand(1));
2209 }
2210 case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
2211 return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
2212 }
2213 case IntrinsicHelper::InvokeRetVoid:
2214 case IntrinsicHelper::InvokeRetBoolean:
2215 case IntrinsicHelper::InvokeRetByte:
2216 case IntrinsicHelper::InvokeRetChar:
2217 case IntrinsicHelper::InvokeRetShort:
2218 case IntrinsicHelper::InvokeRetInt:
2219 case IntrinsicHelper::InvokeRetLong:
2220 case IntrinsicHelper::InvokeRetFloat:
2221 case IntrinsicHelper::InvokeRetDouble:
2222 case IntrinsicHelper::InvokeRetObject: {
2223 return Expand_Invoke(call_inst);
2224 }
Logan Chien75e4b602012-07-23 14:24:12 -07002225
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002226 //==- Math -------------------------------------------------------------==//
2227 case IntrinsicHelper::DivInt: {
2228 return Expand_DivRem(call_inst.getArgOperand(0),
2229 call_inst.getArgOperand(1),
2230 /* is_div */true, kInt);
2231 }
2232 case IntrinsicHelper::RemInt: {
2233 return Expand_DivRem(call_inst.getArgOperand(0),
2234 call_inst.getArgOperand(1),
2235 /* is_div */false, kInt);
2236 }
2237 case IntrinsicHelper::DivLong: {
2238 return Expand_DivRem(call_inst.getArgOperand(0),
2239 call_inst.getArgOperand(1),
2240 /* is_div */true, kLong);
2241 }
2242 case IntrinsicHelper::RemLong: {
2243 return Expand_DivRem(call_inst.getArgOperand(0),
2244 call_inst.getArgOperand(1),
2245 /* is_div */false, kLong);
2246 }
2247 case IntrinsicHelper::D2L: {
2248 return ExpandToRuntime(runtime_support::art_d2l, call_inst);
2249 }
2250 case IntrinsicHelper::D2I: {
2251 return ExpandToRuntime(runtime_support::art_d2i, call_inst);
2252 }
2253 case IntrinsicHelper::F2L: {
2254 return ExpandToRuntime(runtime_support::art_f2l, call_inst);
2255 }
2256 case IntrinsicHelper::F2I: {
2257 return ExpandToRuntime(runtime_support::art_f2i, call_inst);
2258 }
Logan Chien75e4b602012-07-23 14:24:12 -07002259
2260 //==- High-level Static ------------------------------------------------==//
2261 case IntrinsicHelper::HLSget: {
2262 UNIMPLEMENTED(FATAL);
2263 return NULL;
2264 }
2265 case IntrinsicHelper::HLSgetBoolean: {
2266 UNIMPLEMENTED(FATAL);
2267 return NULL;
2268 }
2269 case IntrinsicHelper::HLSgetByte: {
2270 UNIMPLEMENTED(FATAL);
2271 return NULL;
2272 }
2273 case IntrinsicHelper::HLSgetChar: {
2274 UNIMPLEMENTED(FATAL);
2275 return NULL;
2276 }
2277 case IntrinsicHelper::HLSgetShort: {
2278 UNIMPLEMENTED(FATAL);
2279 return NULL;
2280 }
2281 case IntrinsicHelper::HLSgetFloat: {
2282 UNIMPLEMENTED(FATAL);
2283 return NULL;
2284 }
2285 case IntrinsicHelper::HLSgetWide: {
2286 UNIMPLEMENTED(FATAL);
2287 return NULL;
2288 }
2289 case IntrinsicHelper::HLSgetDouble: {
2290 UNIMPLEMENTED(FATAL);
2291 return NULL;
2292 }
2293 case IntrinsicHelper::HLSgetObject: {
2294 UNIMPLEMENTED(FATAL);
2295 return NULL;
2296 }
2297 case IntrinsicHelper::HLSput: {
2298 UNIMPLEMENTED(FATAL);
2299 return NULL;
2300 }
2301 case IntrinsicHelper::HLSputBoolean: {
2302 UNIMPLEMENTED(FATAL);
2303 return NULL;
2304 }
2305 case IntrinsicHelper::HLSputByte: {
2306 UNIMPLEMENTED(FATAL);
2307 return NULL;
2308 }
2309 case IntrinsicHelper::HLSputChar: {
2310 UNIMPLEMENTED(FATAL);
2311 return NULL;
2312 }
2313 case IntrinsicHelper::HLSputShort: {
2314 UNIMPLEMENTED(FATAL);
2315 return NULL;
2316 }
2317 case IntrinsicHelper::HLSputFloat: {
2318 UNIMPLEMENTED(FATAL);
2319 return NULL;
2320 }
2321 case IntrinsicHelper::HLSputWide: {
2322 UNIMPLEMENTED(FATAL);
2323 return NULL;
2324 }
2325 case IntrinsicHelper::HLSputDouble: {
2326 UNIMPLEMENTED(FATAL);
2327 return NULL;
2328 }
2329 case IntrinsicHelper::HLSputObject: {
2330 UNIMPLEMENTED(FATAL);
2331 return NULL;
2332 }
2333
2334 //==- High-level Monitor -----------------------------------------------==//
2335 case IntrinsicHelper::MonitorEnter: {
2336 UNIMPLEMENTED(FATAL);
2337 return NULL;
2338 }
2339 case IntrinsicHelper::MonitorExit: {
2340 UNIMPLEMENTED(FATAL);
2341 return NULL;
2342 }
2343
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002344 //==- Shadow Frame -----------------------------------------------------==//
2345 case IntrinsicHelper::AllocaShadowFrame: {
2346 Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
2347 return NULL;
2348 }
2349 case IntrinsicHelper::SetShadowFrameEntry: {
2350 Expand_SetShadowFrameEntry(call_inst.getArgOperand(0),
2351 call_inst.getArgOperand(1));
2352 return NULL;
2353 }
2354 case IntrinsicHelper::PopShadowFrame: {
2355 Expand_PopShadowFrame();
2356 return NULL;
2357 }
2358 case IntrinsicHelper::UpdateDexPC: {
2359 Expand_UpdateDexPC(call_inst.getArgOperand(0));
2360 return NULL;
2361 }
TDYa127a1b21852012-07-23 03:20:39 -07002362
Logan Chien75e4b602012-07-23 14:24:12 -07002363 //==- Comparison -------------------------------------------------------==//
2364 case IntrinsicHelper::CmplFloat:
2365 case IntrinsicHelper::CmplDouble: {
2366 return Expand_FPCompare(call_inst.getArgOperand(0),
2367 call_inst.getArgOperand(1),
2368 false);
2369 }
2370 case IntrinsicHelper::CmpgFloat:
2371 case IntrinsicHelper::CmpgDouble: {
2372 return Expand_FPCompare(call_inst.getArgOperand(0),
2373 call_inst.getArgOperand(1),
2374 true);
2375 }
2376 case IntrinsicHelper::CmpLong: {
2377 return Expand_LongCompare(call_inst.getArgOperand(0),
2378 call_inst.getArgOperand(1));
2379 }
TDYa127a1b21852012-07-23 03:20:39 -07002380
Logan Chien75e4b602012-07-23 14:24:12 -07002381 //==- Switch -----------------------------------------------------------==//
2382 case greenland::IntrinsicHelper::SparseSwitch: {
TDYa1275e869b62012-07-25 00:45:39 -07002383 // Nothing to be done.
Logan Chien75e4b602012-07-23 14:24:12 -07002384 return NULL;
2385 }
2386 case greenland::IntrinsicHelper::PackedSwitch: {
TDYa1275e869b62012-07-25 00:45:39 -07002387 // Nothing to be done.
Logan Chien75e4b602012-07-23 14:24:12 -07002388 return NULL;
2389 }
2390
2391 //==- Const ------------------------------------------------------------==//
Logan Chiend54a23d2012-07-24 11:19:23 -07002392 case greenland::IntrinsicHelper::ConstInt:
Logan Chien75e4b602012-07-23 14:24:12 -07002393 case greenland::IntrinsicHelper::ConstLong: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002394 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07002395 }
2396 case greenland::IntrinsicHelper::ConstFloat: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002397 return irb_.CreateBitCast(call_inst.getArgOperand(0),
2398 irb_.getJFloatTy());
Logan Chien75e4b602012-07-23 14:24:12 -07002399 }
2400 case greenland::IntrinsicHelper::ConstDouble: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002401 return irb_.CreateBitCast(call_inst.getArgOperand(0),
2402 irb_.getJDoubleTy());
2403 }
2404 case greenland::IntrinsicHelper::ConstObj: {
2405 LOG(FATAL) << "ConstObj should not occur at all";
Logan Chien75e4b602012-07-23 14:24:12 -07002406 return NULL;
2407 }
2408
2409 //==- Method Info ------------------------------------------------------==//
2410 case greenland::IntrinsicHelper::MethodInfo: {
TDYa1275e869b62012-07-25 00:45:39 -07002411 // Nothing to be done.
Logan Chien75e4b602012-07-23 14:24:12 -07002412 return NULL;
2413 }
2414
2415 //==- Copy -------------------------------------------------------------==//
Logan Chiend54a23d2012-07-24 11:19:23 -07002416 case greenland::IntrinsicHelper::CopyInt:
2417 case greenland::IntrinsicHelper::CopyFloat:
2418 case greenland::IntrinsicHelper::CopyLong:
TDYa1275e869b62012-07-25 00:45:39 -07002419 case greenland::IntrinsicHelper::CopyDouble:
Logan Chien75e4b602012-07-23 14:24:12 -07002420 case greenland::IntrinsicHelper::CopyObj: {
Logan Chiend54a23d2012-07-24 11:19:23 -07002421 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07002422 }
2423
2424 //==- Shift ------------------------------------------------------------==//
2425 case greenland::IntrinsicHelper::SHLLong: {
2426 return Expand_IntegerShift(call_inst.getArgOperand(0),
2427 call_inst.getArgOperand(1),
2428 kIntegerSHL, kLong);
2429 }
2430 case greenland::IntrinsicHelper::SHRLong: {
2431 return Expand_IntegerShift(call_inst.getArgOperand(0),
2432 call_inst.getArgOperand(1),
2433 kIntegerSHR, kLong);
2434 }
2435 case greenland::IntrinsicHelper::USHRLong: {
2436 return Expand_IntegerShift(call_inst.getArgOperand(0),
2437 call_inst.getArgOperand(1),
2438 kIntegerUSHR, kLong);
2439 }
2440 case greenland::IntrinsicHelper::SHLInt: {
2441 return Expand_IntegerShift(call_inst.getArgOperand(0),
2442 call_inst.getArgOperand(1),
2443 kIntegerSHL, kInt);
2444 }
2445 case greenland::IntrinsicHelper::SHRInt: {
2446 return Expand_IntegerShift(call_inst.getArgOperand(0),
2447 call_inst.getArgOperand(1),
2448 kIntegerSHR, kInt);
2449 }
2450 case greenland::IntrinsicHelper::USHRInt: {
2451 return Expand_IntegerShift(call_inst.getArgOperand(0),
2452 call_inst.getArgOperand(1),
2453 kIntegerUSHR, kInt);
2454 }
2455
2456 //==- Conversion -------------------------------------------------------==//
TDYa127a1b21852012-07-23 03:20:39 -07002457 case IntrinsicHelper::IntToChar: {
2458 return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
2459 irb_.getJIntTy());
2460 }
2461 case IntrinsicHelper::IntToShort: {
2462 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
2463 irb_.getJIntTy());
2464 }
2465 case IntrinsicHelper::IntToByte: {
2466 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
2467 irb_.getJIntTy());
2468 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002469
Logan Chien75e4b602012-07-23 14:24:12 -07002470 //==- Unknown Cases ----------------------------------------------------==//
2471 case IntrinsicHelper::MaxIntrinsicId:
2472 case IntrinsicHelper::UnknownId:
2473 //default:
2474 // NOTE: "default" is intentionally commented so that C/C++ compiler will
2475 // give some warning on unmatched cases.
2476 // NOTE: We should not implement these cases.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002477 break;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002478 }
Logan Chien75e4b602012-07-23 14:24:12 -07002479 UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002480 return NULL;
2481}
2482
2483} // anonymous namespace
2484
2485namespace art {
2486namespace compiler_llvm {
2487
2488llvm::FunctionPass*
2489CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb) {
2490 return new GBCExpanderPass(intrinsic_helper, irb);
2491}
2492
2493} // namespace compiler_llvm
2494} // namespace art