blob: fa8bceab8bc81782ab9a5cdde5410ba1c4363e5e [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
20#include "greenland/intrinsic_helper.h"
21#include "object.h"
22#include "thread.h"
23
24#include <llvm/ADT/STLExtras.h>
25#include <llvm/Intrinsics.h>
26#include <llvm/Pass.h>
27#include <llvm/Support/CFG.h>
28#include <llvm/Support/InstIterator.h>
29
30#include <vector>
31
32using namespace art;
33using namespace compiler_llvm;
34
35using art::greenland::IntrinsicHelper;
36
37namespace {
38
39class GBCExpanderPass : public llvm::FunctionPass {
40 private:
41 const IntrinsicHelper& intrinsic_helper_;
42 IRBuilder& irb_;
43
44 llvm::LLVMContext& context_;
45 RuntimeSupportBuilder& rtb_;
46
47 private:
48 llvm::AllocaInst* shadow_frame_;
49 llvm::Value* old_shadow_frame_;
50 uint32_t shadow_frame_size_;
51
52 private:
53 //----------------------------------------------------------------------------
Logan Chien75e4b602012-07-23 14:24:12 -070054 // Constant for GBC expansion
55 //----------------------------------------------------------------------------
56 enum IntegerShiftKind {
57 kIntegerSHL,
58 kIntegerSHR,
59 kIntegerUSHR,
60 };
61
62 private:
63 //----------------------------------------------------------------------------
Shih-wei Liao21d28f52012-06-12 05:55:00 -070064 // Helper function for GBC expansion
65 //----------------------------------------------------------------------------
66
67 // Split the basic block containing INST at INST and insert a sequence of
68 // basic blocks with a single entry at BEGIN_BB and a single exit at END_BB
69 // before INST.
70 llvm::BasicBlock*
71 SplitAndInsertBasicBlocksAfter(llvm::BasicBlock::iterator inst,
72 llvm::BasicBlock* begin_bb,
73 llvm::BasicBlock* end_bb);
74
75 llvm::Value* ExpandToRuntime(runtime_support::RuntimeId rt,
76 llvm::CallInst& inst);
77
78 private:
79 // TODO: Almost all Emit* are directly copy-n-paste from MethodCompiler.
80 // Refactor these utility functions from MethodCompiler to avoid forking.
81
82 bool EmitStackOverflowCheck(llvm::Instruction* first_non_alloca);
83
84 //----------------------------------------------------------------------------
85 // Dex cache code generation helper function
86 //----------------------------------------------------------------------------
87 llvm::Value* EmitLoadDexCacheAddr(MemberOffset dex_cache_offset);
88
89 llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
90
91 llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
92
93 llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
94
95 llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
96
97 //----------------------------------------------------------------------------
98 // Code generation helper function
99 //----------------------------------------------------------------------------
100 llvm::Value* EmitLoadMethodObjectAddr();
101
102 llvm::Value* EmitLoadArrayLength(llvm::Value* array);
103
104 llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
105
106 llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
107 llvm::Value* this_addr);
108
109 llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
110 llvm::Value* index_value,
111 JType elem_jty);
112
113 private:
114 //----------------------------------------------------------------------------
115 // Expand Greenland intrinsics
116 //----------------------------------------------------------------------------
117 void Expand_TestSuspend(llvm::CallInst& call_inst);
118
TDYa1279a129452012-07-19 03:10:08 -0700119 void Expand_MarkGCCard(llvm::CallInst& call_inst);
120
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700121 llvm::Value* Expand_GetException();
122
123 llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
124
125 llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
126
127 void Expand_LockObject(llvm::Value* obj);
128
129 void Expand_UnlockObject(llvm::Value* obj);
130
131 llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
132 llvm::Value* index_value,
133 JType elem_jty);
134
135 void Expand_ArrayPut(llvm::Value* new_value,
136 llvm::Value* array_addr,
137 llvm::Value* index_value,
138 JType elem_jty);
139
140 void Expand_FilledNewArray(llvm::CallInst& call_inst);
141
142 llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
143 llvm::Value* is_volatile_value,
144 llvm::Value* object_addr,
145 JType field_jty);
146
147 void Expand_IPutFast(llvm::Value* field_offset_value,
148 llvm::Value* is_volatile_value,
149 llvm::Value* object_addr,
150 llvm::Value* new_value,
151 JType field_jty);
152
153 llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
154 llvm::Value* field_offset_value,
155 llvm::Value* is_volatile_value,
156 JType field_jty);
157
158 void Expand_SPutFast(llvm::Value* static_storage_addr,
159 llvm::Value* field_offset_value,
160 llvm::Value* is_volatile_value,
161 llvm::Value* new_value,
162 JType field_jty);
163
164 llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
165
166 llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
167
168 llvm::Value*
169 Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
170
171 llvm::Value*
172 Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
173 llvm::Value* this_addr);
174
175 llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
176
177 llvm::Value* Expand_DivRem(llvm::Value* dividend, llvm::Value* divisor,
178 bool is_div, JType op_jty);
179
180 void Expand_AllocaShadowFrame(llvm::Value* num_entry_value);
181
182 void Expand_SetShadowFrameEntry(llvm::Value* obj, llvm::Value* entry_idx);
183
184 void Expand_PopShadowFrame();
185
186 void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
187
TDYa127a1b21852012-07-23 03:20:39 -0700188 //----------------------------------------------------------------------------
189 // Quick
190 //----------------------------------------------------------------------------
191
192 llvm::Value* Expand_FPCompare(llvm::Value* src1_value,
193 llvm::Value* src2_value,
194 bool gt_bias);
195
196 llvm::Value* Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value);
197
198 llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
199 llvm::Value* cmp_lt);
200
Logan Chien75e4b602012-07-23 14:24:12 -0700201 //----------------------------------------------------------------------------
202 // Expand Arithmetic Helper Intrinsics
203 //----------------------------------------------------------------------------
204
205 llvm::Value* Expand_IntegerShift(llvm::Value* src1_value,
206 llvm::Value* src2_value,
207 IntegerShiftKind kind,
208 JType op_jty);
209
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700210 public:
211 static char ID;
212
213 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb)
214 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
215 context_(irb.getContext()), rtb_(irb.Runtime())
216 { }
217
218 bool runOnFunction(llvm::Function& func);
219
220 private:
221 bool InsertStackOverflowCheck(llvm::Function& func);
222
223 llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
224 llvm::CallInst& call_inst);
225
226};
227
228char GBCExpanderPass::ID = 0;
229
230bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
TDYa127b672d1e2012-06-28 21:21:45 -0700231 // Runtime support or stub
232 if (func.getName().startswith("art_") || func.getName().startswith("Art")) {
233 return false;
234 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700235 bool changed;
236
TDYa127b672d1e2012-06-28 21:21:45 -0700237 // TODO: Use intrinsic.
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700238 changed = InsertStackOverflowCheck(func);
239
240 std::list<std::pair<llvm::CallInst*,
241 IntrinsicHelper::IntrinsicId> > work_list;
242
243 for (llvm::inst_iterator inst_iter = llvm::inst_begin(func),
244 inst_end = llvm::inst_end(func); inst_iter != inst_end; inst_iter++) {
245 // Only CallInst with its called function is dexlang intrinsic need to
246 // process
247 llvm::Instruction* inst = &*inst_iter;
248 if (llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst)) {
249 const llvm::Function* callee = call_inst->getCalledFunction();
250
251 if (callee != NULL) {
252 IntrinsicHelper::IntrinsicId intr_id =
253 intrinsic_helper_.GetIntrinsicId(callee);
254
255 if (intr_id != IntrinsicHelper::UnknownId) {
256 work_list.push_back(std::make_pair(call_inst, intr_id));
257 }
258 }
259 }
260 }
261
262 changed |= !work_list.empty();
263
264 shadow_frame_ = NULL;
265 old_shadow_frame_ = NULL;
266 shadow_frame_size_ = 0;
267
268 // Remove the instruction containing in the work_list
269 while (!work_list.empty()) {
270 llvm::CallInst* intr_inst = work_list.front().first;
271 IntrinsicHelper::IntrinsicId intr_id = work_list.front().second;
272
273 // Remove the instruction from work list
274 work_list.pop_front();
275
276 // Move the IRBuilder insert pointer
277 irb_.SetInsertPoint(intr_inst);
278
279 // Process the expansion
280 llvm::Value* new_value = ExpandIntrinsic(intr_id, *intr_inst);
281
282 // Use the new value from the expansion
283 if (new_value != NULL) {
284 intr_inst->replaceAllUsesWith(new_value);
285 }
286
287 // Remove the intrinsic instruction
288 intr_inst->eraseFromParent();
289 }
290
291 VERIFY_LLVM_FUNCTION(func);
292
293 return changed;
294}
295
296llvm::BasicBlock*
297GBCExpanderPass::SplitAndInsertBasicBlocksAfter(llvm::BasicBlock::iterator inst,
298 llvm::BasicBlock* begin_bb,
299 llvm::BasicBlock* end_bb) {
300 llvm::BasicBlock* original = inst->getParent();
301 llvm::Function* parent = original->getParent();
302
303 // 1. Create a new basic block A after ORIGINAL
304 llvm::BasicBlock *insert_before =
305 llvm::next(llvm::Function::iterator(original)).getNodePtrUnchecked();
306 llvm::BasicBlock* a =
307 llvm::BasicBlock::Create(context_, "", parent, insert_before);
308
309 // 2. Move all instructions in ORIGINAL after INST (included) to A
310 a->getInstList().splice(a->end(), original->getInstList(),
311 inst, original->end());
312
313 // 3. Add an unconditional branch in ORIGINAL to begin_bb
314 llvm::BranchInst::Create(begin_bb, original);
315
316 // 4. Add an unconditional branch in END_BB to A
317 llvm::BranchInst::Create(a, end_bb);
318
319 // 5. Update the PHI nodes in the successors of A. Update the PHI node entry
320 // with incoming basic block from ORIGINAL to A
321 for (llvm::succ_iterator succ_iter = llvm::succ_begin(a),
322 succ_end = llvm::succ_end(a); succ_iter != succ_end; succ_iter++) {
323 llvm::BasicBlock* succ = *succ_iter;
324 llvm::PHINode* phi;
325 for (llvm::BasicBlock::iterator inst_iter = succ->begin();
326 (phi = llvm::dyn_cast<llvm::PHINode>(inst_iter)); ++inst_iter) {
327 int idx;
328 while ((idx = phi->getBasicBlockIndex(original)) != -1) {
329 phi->setIncomingBlock(static_cast<unsigned>(idx), a);
330 }
331 }
332 }
333
334 return a;
335}
336
337llvm::Value* GBCExpanderPass::ExpandToRuntime(runtime_support::RuntimeId rt,
338 llvm::CallInst& inst) {
339 // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
340 // the arguments passed to the GBC intrinsic are as the same as IBC runtime
341 // function, therefore only called function is needed to change.
342 unsigned num_args = inst.getNumArgOperands();
343
344 if (num_args <= 0) {
345 return irb_.CreateCall(irb_.GetRuntime(rt));
346 } else {
347 std::vector<llvm::Value*> args;
348 for (unsigned i = 0; i < num_args; i++) {
349 args.push_back(inst.getArgOperand(i));
350 }
351
352 return irb_.CreateCall(irb_.GetRuntime(rt), args);
353 }
354}
355
356bool
357GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
358 llvm::Function* func = first_non_alloca->getParent()->getParent();
359 llvm::Module* module = func->getParent();
360
361 llvm::BasicBlock* block_entry =
362 llvm::BasicBlock::Create(context_, "stack_overflow_entry", func);
363
364 irb_.SetInsertPoint(block_entry);
365
366 // Call llvm intrinsic function to get frame address.
367 llvm::Function* frameaddress =
368 llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
369
370 // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
371 llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
372
373 // Cast i8* to int
374 frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
375
376 // Get thread.stack_end_
377 llvm::Value* stack_end =
378 irb_.Runtime().EmitLoadFromThreadOffset(Thread::StackEndOffset().Int32Value(),
379 irb_.getPtrEquivIntTy(),
380 kTBAARuntimeInfo);
381
382 // Check the frame address < thread.stack_end_ ?
383 llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
384
385 llvm::BasicBlock* block_exception =
386 llvm::BasicBlock::Create(context_, "stack_overflow", func);
387
388 llvm::BasicBlock* block_continue =
389 llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
390
391 irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
392
393 // If stack overflow, throw exception.
394 irb_.SetInsertPoint(block_exception);
395 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowStackOverflowException));
396
397 // Unwind.
398 llvm::Type* ret_type = func->getReturnType();
399 if (ret_type->isVoidTy()) {
400 irb_.CreateRetVoid();
401 } else {
402 // The return value is ignored when there's an exception. MethodCompiler
403 // returns zero value under the the corresponding return type in this case.
404 // GBCExpander returns LLVM undef value here for brevity
405 irb_.CreateRet(llvm::UndefValue::get(ret_type));
406 }
407
408 irb_.SetInsertPoint(block_continue);
409
410 SplitAndInsertBasicBlocksAfter(*first_non_alloca, block_entry, block_continue);
411
412 return true;
413}
414
415llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(MemberOffset offset) {
416 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
417
418 return irb_.LoadFromObjectOffset(method_object_addr,
419 offset.Int32Value(),
420 irb_.getJObjectTy(),
421 kTBAAConstJObject);
422}
423
424llvm::Value*
425GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
426 llvm::Value* static_storage_dex_cache_addr =
427 EmitLoadDexCacheAddr(Method::DexCacheInitializedStaticStorageOffset());
428
429 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
430
431 return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
432}
433
434llvm::Value*
435GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
436 llvm::Value* resolved_type_dex_cache_addr =
437 EmitLoadDexCacheAddr(Method::DexCacheResolvedTypesOffset());
438
439 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
440
441 return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
442}
443
444llvm::Value* GBCExpanderPass::
445EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
446 llvm::Value* resolved_method_dex_cache_addr =
447 EmitLoadDexCacheAddr(Method::DexCacheResolvedMethodsOffset());
448
449 llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
450
451 return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
452}
453
454llvm::Value* GBCExpanderPass::
455EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
456 llvm::Value* string_dex_cache_addr =
457 EmitLoadDexCacheAddr(Method::DexCacheStringsOffset());
458
459 llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
460
461 return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
462}
463
464llvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
465 llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
466 return parent_func->arg_begin();
467}
468
469llvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
470 // Load array length
471 return irb_.LoadFromObjectOffset(array,
472 Array::LengthOffset().Int32Value(),
473 irb_.getJIntTy(),
474 kTBAAConstJObject);
475
476}
477
478llvm::Value*
479GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
480 llvm::Value* callee_method_object_field_addr =
481 EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
482
483 return irb_.CreateLoad(callee_method_object_field_addr, kTBAAJRuntime);
484}
485
486llvm::Value* GBCExpanderPass::
487EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
488 // Load class object of *this* pointer
489 llvm::Value* class_object_addr =
490 irb_.LoadFromObjectOffset(this_addr,
491 Object::ClassOffset().Int32Value(),
492 irb_.getJObjectTy(),
493 kTBAAConstJObject);
494
495 // Load vtable address
496 llvm::Value* vtable_addr =
497 irb_.LoadFromObjectOffset(class_object_addr,
498 Class::VTableOffset().Int32Value(),
499 irb_.getJObjectTy(),
500 kTBAAConstJObject);
501
502 // Load callee method object
503 llvm::Value* vtable_idx_value =
504 irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
505
506 llvm::Value* method_field_addr =
507 EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
508
509 return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
510}
511
512// Emit Array GetElementPtr
513llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
514 llvm::Value* index_value,
515 JType elem_jty) {
516
517 int data_offset;
518 if (elem_jty == kLong || elem_jty == kDouble ||
519 (elem_jty == kObject && sizeof(uint64_t) == sizeof(Object*))) {
520 data_offset = Array::DataOffset(sizeof(int64_t)).Int32Value();
521 } else {
522 data_offset = Array::DataOffset(sizeof(int32_t)).Int32Value();
523 }
524
525 llvm::Constant* data_offset_value =
526 irb_.getPtrEquivInt(data_offset);
527
528 llvm::Type* elem_type = irb_.getJType(elem_jty, kArray);
529
530 llvm::Value* array_data_addr =
531 irb_.CreatePtrDisp(array_addr, data_offset_value,
532 elem_type->getPointerTo());
533
534 return irb_.CreateGEP(array_data_addr, index_value);
535}
536
537void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
538 llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
539 llvm::BasicBlock* suspend_test_begin_bb =
540 llvm::BasicBlock::Create(context_, "suspend_test", parent_func);
541
542 irb_.SetInsertPoint(suspend_test_begin_bb);
543 irb_.Runtime().EmitTestSuspend();
544
545 llvm::BasicBlock* suspend_test_end_bb = irb_.GetInsertBlock();
546
547 SplitAndInsertBasicBlocksAfter(call_inst, suspend_test_begin_bb,
548 suspend_test_end_bb);
549 return;
550}
551
TDYa1279a129452012-07-19 03:10:08 -0700552void GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
553 llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
554 llvm::BasicBlock* begin_bb =
555 llvm::BasicBlock::Create(context_, "mark_gc_card", parent_func);
556
557 irb_.SetInsertPoint(begin_bb);
558 irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
559
560 llvm::BasicBlock* end_bb = irb_.GetInsertBlock();
561
562 SplitAndInsertBasicBlocksAfter(call_inst, begin_bb, end_bb);
563 return;
564}
565
Shih-wei Liao21d28f52012-06-12 05:55:00 -0700566llvm::Value* GBCExpanderPass::Expand_GetException() {
567 // Get thread-local exception field address
568 llvm::Value* exception_object_addr =
569 irb_.Runtime().EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
570 irb_.getJObjectTy(),
571 kTBAAJRuntime);
572
573 // Set thread-local exception field address to NULL
574 irb_.Runtime().EmitStoreToThreadOffset(Thread::ExceptionOffset().Int32Value(),
575 irb_.getJNull(),
576 kTBAAJRuntime);
577
578 return exception_object_addr;
579}
580
581llvm::Value*
582GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
583 uint32_t string_idx =
584 llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
585
586 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
587
588 return irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
589}
590
591llvm::Value*
592GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
593 uint32_t type_idx =
594 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
595
596 llvm::Value* type_field_addr =
597 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
598
599 return irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
600}
601
602void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
603 llvm::BasicBlock::iterator lock_obj_inst = irb_.GetInsertPoint();
604 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
605
606 llvm::BasicBlock* lock_obj_begin_bb =
607 llvm::BasicBlock::Create(context_, "", parent);
608
609 irb_.SetInsertPoint(lock_obj_begin_bb);
610 rtb_.EmitLockObject(obj);
611
612 llvm::BasicBlock* lock_obj_end_bb = irb_.GetInsertBlock();
613
614 SplitAndInsertBasicBlocksAfter(lock_obj_inst, lock_obj_begin_bb,
615 lock_obj_end_bb);
616
617 return;
618}
619
620void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
621 llvm::BasicBlock::iterator unlock_obj_inst = irb_.GetInsertPoint();
622 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
623
624 llvm::BasicBlock* unlock_obj_begin_bb =
625 llvm::BasicBlock::Create(context_, "", parent);
626
627 irb_.SetInsertPoint(unlock_obj_begin_bb);
628 rtb_.EmitUnlockObject(obj);
629
630 llvm::BasicBlock* unlock_obj_end_bb = irb_.GetInsertBlock();
631
632 SplitAndInsertBasicBlocksAfter(unlock_obj_inst, unlock_obj_begin_bb,
633 unlock_obj_end_bb);
634
635 return;
636}
637
638llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
639 llvm::Value* index_value,
640 JType elem_jty) {
641 llvm::Value* array_elem_addr =
642 EmitArrayGEP(array_addr, index_value, elem_jty);
643
644 return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
645}
646
647void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
648 llvm::Value* array_addr,
649 llvm::Value* index_value,
650 JType elem_jty) {
651 llvm::Value* array_elem_addr =
652 EmitArrayGEP(array_addr, index_value, elem_jty);
653
654 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
655
656 return;
657}
658
659void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
660 // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
661 llvm::Value* array = call_inst.getArgOperand(0);
662
663 uint32_t element_jty =
664 llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
665
666 DCHECK(call_inst.getNumArgOperands() > 2);
667 unsigned num_elements = (call_inst.getNumArgOperands() - 2);
668
669 bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
670
671 uint32_t alignment;
672 llvm::Constant* elem_size;
673 llvm::PointerType* field_type;
674
675 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
676 // as the element, thus we are only checking 2 cases: primitive int and
677 // non-primitive type.
678 if (is_elem_int_ty) {
679 alignment = sizeof(int32_t);
680 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
681 field_type = irb_.getJIntTy()->getPointerTo();
682 } else {
683 alignment = irb_.getSizeOfPtrEquivInt();
684 elem_size = irb_.getSizeOfPtrEquivIntValue();
685 field_type = irb_.getJObjectTy()->getPointerTo();
686 }
687
688 llvm::Value* data_field_offset =
689 irb_.getPtrEquivInt(Array::DataOffset(alignment).Int32Value());
690
691 llvm::Value* data_field_addr =
692 irb_.CreatePtrDisp(array, data_field_offset, field_type);
693
694 for (unsigned i = 0; i < num_elements; ++i) {
695 // Values to fill the array begin at the 3rd argument
696 llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
697
698 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
699
700 data_field_addr =
701 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
702 }
703
704 return;
705}
706
707llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
708 llvm::Value* /*is_volatile_value*/,
709 llvm::Value* object_addr,
710 JType field_jty) {
711 int field_offset =
712 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
713
714 DCHECK_GE(field_offset, 0);
715
716 llvm::PointerType* field_type =
717 irb_.getJType(field_jty, kField)->getPointerTo();
718
719 field_offset_value = irb_.getPtrEquivInt(field_offset);
720
721 llvm::Value* field_addr =
722 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
723
724 // TODO: Check is_volatile. We need to generate atomic load instruction
725 // when is_volatile is true.
726 return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
727}
728
729void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
730 llvm::Value* /* is_volatile_value */,
731 llvm::Value* object_addr,
732 llvm::Value* new_value,
733 JType field_jty) {
734 int field_offset =
735 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
736
737 DCHECK_GE(field_offset, 0);
738
739 llvm::PointerType* field_type =
740 irb_.getJType(field_jty, kField)->getPointerTo();
741
742 field_offset_value = irb_.getPtrEquivInt(field_offset);
743
744 llvm::Value* field_addr =
745 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
746
747 // TODO: Check is_volatile. We need to generate atomic store instruction
748 // when is_volatile is true.
749 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
750
751 return;
752}
753
754llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
755 llvm::Value* field_offset_value,
756 llvm::Value* /*is_volatile_value*/,
757 JType field_jty) {
758 int field_offset =
759 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
760
761 DCHECK_GE(field_offset, 0);
762
763 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
764
765 llvm::Value* static_field_addr =
766 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
767 irb_.getJType(field_jty, kField)->getPointerTo());
768
769 // TODO: Check is_volatile. We need to generate atomic store instruction
770 // when is_volatile is true.
771 return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
772}
773
774void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
775 llvm::Value* field_offset_value,
776 llvm::Value* /* is_volatile_value */,
777 llvm::Value* new_value,
778 JType field_jty) {
779 int field_offset =
780 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
781
782 DCHECK_GE(field_offset, 0);
783
784 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
785
786 llvm::Value* static_field_addr =
787 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
788 irb_.getJType(field_jty, kField)->getPointerTo());
789
790 // TODO: Check is_volatile. We need to generate atomic store instruction
791 // when is_volatile is true.
792 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
793
794 return;
795}
796
797llvm::Value*
798GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
799 return irb_.LoadFromObjectOffset(method_object_addr,
800 Method::DeclaringClassOffset().Int32Value(),
801 irb_.getJObjectTy(),
802 kTBAAConstJObject);
803}
804
805llvm::Value*
806GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
807 uint32_t type_idx =
808 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
809
810 llvm::Value* storage_field_addr =
811 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
812
813 return irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
814}
815
816llvm::Value*
817GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
818 uint32_t callee_method_idx =
819 llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
820
821 return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
822}
823
824llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
825 llvm::Value* vtable_idx_value,
826 llvm::Value* this_addr) {
827 int vtable_idx =
828 llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
829
830 return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
831}
832
833llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
834 // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
835 llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
836 unsigned num_args = call_inst.getNumArgOperands();
837 llvm::Type* ret_type = call_inst.getType();
838
839 // Determine the function type of the callee method
840 std::vector<llvm::Type*> args_type;
841 std::vector<llvm::Value*> args;
842 for (unsigned i = 0; i < num_args; i++) {
843 args.push_back(call_inst.getArgOperand(i));
844 args_type.push_back(args[i]->getType());
845 }
846
847 llvm::FunctionType* callee_method_type =
848 llvm::FunctionType::get(ret_type, args_type, false);
849
850 llvm::Value* code_addr =
851 irb_.LoadFromObjectOffset(callee_method_object_addr,
852 Method::GetCodeOffset().Int32Value(),
853 callee_method_type->getPointerTo(),
854 kTBAAJRuntime);
855
856 // Invoke callee
857 llvm::Value* retval = irb_.CreateCall(code_addr, args);
858
859 return retval;
860}
861
862llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::Value* dividend,
863 llvm::Value* divisor,
864 bool is_div, JType op_jty) {
865 // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
866
867 // Check the special case: MININT / -1 = MININT
868 // That case will cause overflow, which is undefined behavior in llvm.
869 // So we check the divisor is -1 or not, if the divisor is -1, we do
870 // the special path to avoid undefined behavior.
871 llvm::Type* op_type = irb_.getJType(op_jty, kAccurate);
872 llvm::Value* zero = irb_.getJZero(op_jty);
873 llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
874
875 llvm::BasicBlock::iterator div_rem_inst = irb_.GetInsertPoint();
876 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
877
878 llvm::BasicBlock* begin_div_rem =
879 llvm::BasicBlock::Create(context_, "", parent);
880 llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
881 llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
882 llvm::BasicBlock* neg_one_cont =
883 llvm::BasicBlock::Create(context_, "", parent);
884
885 irb_.SetInsertPoint(begin_div_rem);
886 llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
887 irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
888
889 // If divisor == -1
890 irb_.SetInsertPoint(eq_neg_one);
891 llvm::Value* eq_result;
892 if (is_div) {
893 // We can just change from "dividend div -1" to "neg dividend". The sub
894 // don't care the sign/unsigned because of two's complement representation.
895 // And the behavior is what we want:
896 // -(2^n) (2^n)-1
897 // MININT < k <= MAXINT -> mul k -1 = -k
898 // MININT == k -> mul k -1 = k
899 //
900 // LLVM use sub to represent 'neg'
901 eq_result = irb_.CreateSub(zero, dividend);
902 } else {
903 // Everything modulo -1 will be 0.
904 eq_result = zero;
905 }
906 irb_.CreateBr(neg_one_cont);
907
908 // If divisor != -1, just do the division.
909 irb_.SetInsertPoint(ne_neg_one);
910 llvm::Value* ne_result;
911 if (is_div) {
912 ne_result = irb_.CreateSDiv(dividend, divisor);
913 } else {
914 ne_result = irb_.CreateSRem(dividend, divisor);
915 }
916 irb_.CreateBr(neg_one_cont);
917
918 irb_.SetInsertPoint(neg_one_cont);
919 llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
920 result->addIncoming(eq_result, eq_neg_one);
921 result->addIncoming(ne_result, ne_neg_one);
922
923 SplitAndInsertBasicBlocksAfter(div_rem_inst, begin_div_rem, neg_one_cont);
924
925 return result;
926}
927
928void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value) {
929 // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
930 // MethodCompiler::EmitPushShadowFrame
931 shadow_frame_size_ =
932 llvm::cast<llvm::ConstantInt>(num_entry_value)->getZExtValue();
933
934 llvm::StructType* shadow_frame_type =
935 irb_.getShadowFrameTy(shadow_frame_size_);
936
937 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
938
939 // Alloca a pointer to old shadow frame
940 old_shadow_frame_ =
941 irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
942
943 // Zero-initialization of the shadow frame table
944 llvm::Value* shadow_frame_table =
945 irb_.CreateConstGEP2_32(shadow_frame_, 0, 1);
946 llvm::Type* table_type = shadow_frame_type->getElementType(1);
947
948 llvm::ConstantAggregateZero* zero_initializer =
949 llvm::ConstantAggregateZero::get(table_type);
950
951 irb_.CreateStore(zero_initializer, shadow_frame_table, kTBAAShadowFrame);
952
953 // Push the shadow frame
954 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
955
956 // Push the shadow frame
957 llvm::Value* shadow_frame_upcast =
958 irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
959
960 llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
961 method_object_addr,
962 shadow_frame_size_);
963
964 irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
965
966 return;
967}
968
969void GBCExpanderPass::Expand_SetShadowFrameEntry(llvm::Value* obj,
970 llvm::Value* entry_idx) {
971 DCHECK(shadow_frame_ != NULL);
972
973 llvm::Value* gep_index[] = {
974 irb_.getInt32(0), // No pointer displacement
975 irb_.getInt32(1), // SIRT
976 entry_idx // Pointer field
977 };
978
979 llvm::Value* entry_addr = irb_.CreateGEP(shadow_frame_, gep_index);
980 irb_.CreateStore(obj, entry_addr, kTBAAShadowFrame);
981 return;
982}
983
984void GBCExpanderPass::Expand_PopShadowFrame() {
985 rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
986 return;
987}
988
989void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
990 irb_.StoreToObjectOffset(shadow_frame_,
991 ShadowFrame::DexPCOffset(),
992 dex_pc_value,
993 kTBAAShadowFrame);
994 return;
995}
996
997bool GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
998 // DexLang generates all alloca instruction in the first basic block of the
999 // FUNC and also there's no any alloca instructions after the first non-alloca
1000 // instruction
1001
1002 llvm::BasicBlock::iterator first_non_alloca = func.front().begin();
1003 while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
1004 ++first_non_alloca;
1005 }
1006
1007 // Insert stack overflow check codes before first_non_alloca (i.e., after all
1008 // alloca instructions)
1009 return EmitStackOverflowCheck(&*first_non_alloca);
1010}
1011
TDYa127a1b21852012-07-23 03:20:39 -07001012llvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
1013 llvm::Value* src2_value,
1014 bool gt_bias) {
1015 llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
1016 llvm::Value* cmp_lt;
1017
1018 if (gt_bias) {
1019 cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
1020 } else {
1021 cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
1022 }
1023
1024 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1025}
1026
1027llvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
1028 llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
1029 llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
1030
1031 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1032}
1033
1034llvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
1035 llvm::Value* cmp_lt) {
1036
1037 llvm::Constant* zero = irb_.getJInt(0);
1038 llvm::Constant* pos1 = irb_.getJInt(1);
1039 llvm::Constant* neg1 = irb_.getJInt(-1);
1040
1041 llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
1042 llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
1043
1044 return result_eq;
1045}
1046
Logan Chien75e4b602012-07-23 14:24:12 -07001047llvm::Value* GBCExpanderPass::Expand_IntegerShift(llvm::Value* src1_value,
1048 llvm::Value* src2_value,
1049 IntegerShiftKind kind,
1050 JType op_jty) {
1051 DCHECK(op_jty == kInt || op_jty == kLong);
1052
1053 // Mask and zero-extend RHS properly
1054 if (op_jty == kInt) {
1055 src2_value = irb_.CreateAnd(src2_value, 0x1f);
1056 } else {
1057 llvm::Value* masked_src2_value = irb_.CreateAnd(src2_value, 0x3f);
1058 src2_value = irb_.CreateZExt(masked_src2_value, irb_.getJLongTy());
1059 }
1060
1061 // Create integer shift llvm instruction
1062 switch (kind) {
1063 case kIntegerSHL:
1064 return irb_.CreateShl(src1_value, src2_value);
1065
1066 case kIntegerSHR:
1067 return irb_.CreateAShr(src1_value, src2_value);
1068
1069 case kIntegerUSHR:
1070 return irb_.CreateLShr(src1_value, src2_value);
1071
1072 default:
1073 LOG(FATAL) << "Unknown integer shift kind: " << kind;
1074 return NULL;
1075 }
1076}
1077
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001078llvm::Value*
1079GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
1080 llvm::CallInst& call_inst) {
1081 switch (intr_id) {
1082 //==- Thread -----------------------------------------------------------==//
1083 case IntrinsicHelper::GetCurrentThread: {
TDYa127b672d1e2012-06-28 21:21:45 -07001084 return irb_.Runtime().EmitGetCurrentThread();
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001085 }
Logan Chiend54a23d2012-07-24 11:19:23 -07001086 case IntrinsicHelper::TestSuspend:
Logan Chien75e4b602012-07-23 14:24:12 -07001087 case IntrinsicHelper::CheckSuspend: {
Logan Chiend54a23d2012-07-24 11:19:23 -07001088 Expand_TestSuspend(call_inst);
Logan Chien75e4b602012-07-23 14:24:12 -07001089 return NULL;
1090 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001091 case IntrinsicHelper::MarkGCCard: {
TDYa1279a129452012-07-19 03:10:08 -07001092 Expand_MarkGCCard(call_inst);
1093 return NULL;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001094 }
Logan Chien75e4b602012-07-23 14:24:12 -07001095
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001096 //==- Exception --------------------------------------------------------==//
1097 case IntrinsicHelper::ThrowException: {
1098 return ExpandToRuntime(runtime_support::ThrowException, call_inst);
1099 }
1100 case IntrinsicHelper::GetException: {
1101 return Expand_GetException();
1102 }
1103 case IntrinsicHelper::IsExceptionPending: {
1104 return irb_.Runtime().EmitIsExceptionPending();
1105 }
1106 case IntrinsicHelper::FindCatchBlock: {
1107 return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
1108 }
1109 case IntrinsicHelper::ThrowDivZeroException: {
1110 return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
1111 }
1112 case IntrinsicHelper::ThrowNullPointerException: {
1113 return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
1114 }
1115 case IntrinsicHelper::ThrowIndexOutOfBounds: {
1116 return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
1117 }
Logan Chien75e4b602012-07-23 14:24:12 -07001118
1119 //==- Const String -----------------------------------------------------==//
1120 case IntrinsicHelper::ConstString: {
1121 UNIMPLEMENTED(FATAL);
1122 return NULL;
1123 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001124 case IntrinsicHelper::LoadStringFromDexCache: {
1125 return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
1126 }
1127 case IntrinsicHelper::ResolveString: {
1128 return ExpandToRuntime(runtime_support::ResolveString, call_inst);
1129 }
Logan Chien75e4b602012-07-23 14:24:12 -07001130
1131 //==- Const Class ------------------------------------------------------==//
1132 case IntrinsicHelper::ConstClass: {
1133 UNIMPLEMENTED(FATAL);
1134 return NULL;
1135 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001136 case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
1137 return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
1138 }
1139 case IntrinsicHelper::LoadTypeFromDexCache: {
1140 return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
1141 }
1142 case IntrinsicHelper::InitializeType: {
1143 return ExpandToRuntime(runtime_support::InitializeType, call_inst);
1144 }
Logan Chien75e4b602012-07-23 14:24:12 -07001145
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001146 //==- Lock -------------------------------------------------------------==//
1147 case IntrinsicHelper::LockObject: {
1148 Expand_LockObject(call_inst.getArgOperand(0));
1149 return NULL;
1150 }
1151 case IntrinsicHelper::UnlockObject: {
1152 Expand_UnlockObject(call_inst.getArgOperand(0));
1153 return NULL;
1154 }
Logan Chien75e4b602012-07-23 14:24:12 -07001155
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001156 //==- Cast -------------------------------------------------------------==//
1157 case IntrinsicHelper::CheckCast: {
1158 return ExpandToRuntime(runtime_support::CheckCast, call_inst);
1159 }
Logan Chien75e4b602012-07-23 14:24:12 -07001160 case IntrinsicHelper::HLCheckCast: {
1161 UNIMPLEMENTED(FATAL);
1162 return NULL;
1163 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001164 case IntrinsicHelper::IsAssignable: {
1165 return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
1166 }
Logan Chien75e4b602012-07-23 14:24:12 -07001167
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001168 //==- Alloc ------------------------------------------------------------==//
1169 case IntrinsicHelper::AllocObject: {
1170 return ExpandToRuntime(runtime_support::AllocObject, call_inst);
1171 }
1172 case IntrinsicHelper::AllocObjectWithAccessCheck: {
1173 return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
1174 }
Logan Chien75e4b602012-07-23 14:24:12 -07001175
1176 //==- Instance ---------------------------------------------------------==//
1177 case IntrinsicHelper::NewInstance: {
1178 UNIMPLEMENTED(FATAL);
1179 return NULL;
1180 }
1181 case IntrinsicHelper::InstanceOf: {
1182 UNIMPLEMENTED(FATAL);
1183 return NULL;
1184 }
1185
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001186 //==- Array ------------------------------------------------------------==//
Logan Chien75e4b602012-07-23 14:24:12 -07001187 case IntrinsicHelper::NewArray: {
1188 UNIMPLEMENTED(FATAL);
1189 return NULL;
1190 }
1191 case IntrinsicHelper::OptArrayLength: {
1192 UNIMPLEMENTED(FATAL);
1193 return NULL;
1194 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001195 case IntrinsicHelper::ArrayLength: {
1196 return EmitLoadArrayLength(call_inst.getArgOperand(0));
1197 }
1198 case IntrinsicHelper::AllocArray: {
1199 return ExpandToRuntime(runtime_support::AllocArray, call_inst);
1200 }
1201 case IntrinsicHelper::AllocArrayWithAccessCheck: {
1202 return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
1203 call_inst);
1204 }
1205 case IntrinsicHelper::CheckAndAllocArray: {
1206 return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
1207 }
1208 case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
1209 return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
1210 call_inst);
1211 }
1212 case IntrinsicHelper::ArrayGet: {
1213 return Expand_ArrayGet(call_inst.getArgOperand(0),
1214 call_inst.getArgOperand(1),
1215 kInt);
1216 }
1217 case IntrinsicHelper::ArrayGetWide: {
1218 return Expand_ArrayGet(call_inst.getArgOperand(0),
1219 call_inst.getArgOperand(1),
1220 kLong);
1221 }
1222 case IntrinsicHelper::ArrayGetObject: {
1223 return Expand_ArrayGet(call_inst.getArgOperand(0),
1224 call_inst.getArgOperand(1),
1225 kObject);
1226 }
1227 case IntrinsicHelper::ArrayGetBoolean: {
1228 return Expand_ArrayGet(call_inst.getArgOperand(0),
1229 call_inst.getArgOperand(1),
1230 kBoolean);
1231 }
1232 case IntrinsicHelper::ArrayGetByte: {
1233 return Expand_ArrayGet(call_inst.getArgOperand(0),
1234 call_inst.getArgOperand(1),
1235 kByte);
1236 }
1237 case IntrinsicHelper::ArrayGetChar: {
1238 return Expand_ArrayGet(call_inst.getArgOperand(0),
1239 call_inst.getArgOperand(1),
1240 kChar);
1241 }
1242 case IntrinsicHelper::ArrayGetShort: {
1243 return Expand_ArrayGet(call_inst.getArgOperand(0),
1244 call_inst.getArgOperand(1),
1245 kShort);
1246 }
1247 case IntrinsicHelper::ArrayPut: {
1248 Expand_ArrayPut(call_inst.getArgOperand(0),
1249 call_inst.getArgOperand(1),
1250 call_inst.getArgOperand(2),
1251 kInt);
1252 return NULL;
1253 }
1254 case IntrinsicHelper::ArrayPutWide: {
1255 Expand_ArrayPut(call_inst.getArgOperand(0),
1256 call_inst.getArgOperand(1),
1257 call_inst.getArgOperand(2),
1258 kLong);
1259 return NULL;
1260 }
1261 case IntrinsicHelper::ArrayPutObject: {
1262 Expand_ArrayPut(call_inst.getArgOperand(0),
1263 call_inst.getArgOperand(1),
1264 call_inst.getArgOperand(2),
1265 kObject);
1266 return NULL;
1267 }
1268 case IntrinsicHelper::ArrayPutBoolean: {
1269 Expand_ArrayPut(call_inst.getArgOperand(0),
1270 call_inst.getArgOperand(1),
1271 call_inst.getArgOperand(2),
1272 kBoolean);
1273 return NULL;
1274 }
1275 case IntrinsicHelper::ArrayPutByte: {
1276 Expand_ArrayPut(call_inst.getArgOperand(0),
1277 call_inst.getArgOperand(1),
1278 call_inst.getArgOperand(2),
1279 kByte);
1280 return NULL;
1281 }
1282 case IntrinsicHelper::ArrayPutChar: {
1283 Expand_ArrayPut(call_inst.getArgOperand(0),
1284 call_inst.getArgOperand(1),
1285 call_inst.getArgOperand(2),
1286 kChar);
1287 return NULL;
1288 }
1289 case IntrinsicHelper::ArrayPutShort: {
1290 Expand_ArrayPut(call_inst.getArgOperand(0),
1291 call_inst.getArgOperand(1),
1292 call_inst.getArgOperand(2),
1293 kShort);
1294 return NULL;
1295 }
1296 case IntrinsicHelper::CheckPutArrayElement: {
1297 return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
1298 }
1299 case IntrinsicHelper::FilledNewArray: {
1300 Expand_FilledNewArray(call_inst);
1301 return NULL;
1302 }
1303 case IntrinsicHelper::FillArrayData: {
1304 return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
1305 }
Logan Chien75e4b602012-07-23 14:24:12 -07001306 case IntrinsicHelper::HLFillArrayData: {
1307 UNIMPLEMENTED(FATAL);
1308 return NULL;
1309 }
1310 case IntrinsicHelper::HLFilledNewArray: {
1311 UNIMPLEMENTED(FATAL);
1312 return NULL;
1313 }
1314
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001315 //==- Instance Field ---------------------------------------------------==//
1316 case IntrinsicHelper::InstanceFieldGet:
1317 case IntrinsicHelper::InstanceFieldGetBoolean:
1318 case IntrinsicHelper::InstanceFieldGetByte:
1319 case IntrinsicHelper::InstanceFieldGetChar:
1320 case IntrinsicHelper::InstanceFieldGetShort: {
1321 return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
1322 }
1323 case IntrinsicHelper::InstanceFieldGetWide: {
1324 return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
1325 }
1326 case IntrinsicHelper::InstanceFieldGetObject: {
1327 return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
1328 }
1329 case IntrinsicHelper::InstanceFieldGetFast: {
1330 return Expand_IGetFast(call_inst.getArgOperand(0),
1331 call_inst.getArgOperand(1),
1332 call_inst.getArgOperand(2),
1333 kInt);
1334 }
1335 case IntrinsicHelper::InstanceFieldGetWideFast: {
1336 return Expand_IGetFast(call_inst.getArgOperand(0),
1337 call_inst.getArgOperand(1),
1338 call_inst.getArgOperand(2),
1339 kLong);
1340 }
1341 case IntrinsicHelper::InstanceFieldGetObjectFast: {
1342 return Expand_IGetFast(call_inst.getArgOperand(0),
1343 call_inst.getArgOperand(1),
1344 call_inst.getArgOperand(2),
1345 kObject);
1346 }
1347 case IntrinsicHelper::InstanceFieldGetBooleanFast: {
1348 return Expand_IGetFast(call_inst.getArgOperand(0),
1349 call_inst.getArgOperand(1),
1350 call_inst.getArgOperand(2),
1351 kBoolean);
1352 }
1353 case IntrinsicHelper::InstanceFieldGetByteFast: {
1354 return Expand_IGetFast(call_inst.getArgOperand(0),
1355 call_inst.getArgOperand(1),
1356 call_inst.getArgOperand(2),
1357 kByte);
1358 }
1359 case IntrinsicHelper::InstanceFieldGetCharFast: {
1360 return Expand_IGetFast(call_inst.getArgOperand(0),
1361 call_inst.getArgOperand(1),
1362 call_inst.getArgOperand(2),
1363 kChar);
1364 }
1365 case IntrinsicHelper::InstanceFieldGetShortFast: {
1366 return Expand_IGetFast(call_inst.getArgOperand(0),
1367 call_inst.getArgOperand(1),
1368 call_inst.getArgOperand(2),
1369 kShort);
1370 }
1371 case IntrinsicHelper::InstanceFieldPut:
1372 case IntrinsicHelper::InstanceFieldPutBoolean:
1373 case IntrinsicHelper::InstanceFieldPutByte:
1374 case IntrinsicHelper::InstanceFieldPutChar:
1375 case IntrinsicHelper::InstanceFieldPutShort: {
1376 return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
1377 }
1378 case IntrinsicHelper::InstanceFieldPutWide: {
1379 return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
1380 }
1381 case IntrinsicHelper::InstanceFieldPutObject: {
1382 return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
1383 }
1384 case IntrinsicHelper::InstanceFieldPutFast: {
1385 Expand_IPutFast(call_inst.getArgOperand(0),
1386 call_inst.getArgOperand(1),
1387 call_inst.getArgOperand(2),
1388 call_inst.getArgOperand(3),
1389 kInt);
1390 return NULL;
1391 }
1392 case IntrinsicHelper::InstanceFieldPutWideFast: {
1393 Expand_IPutFast(call_inst.getArgOperand(0),
1394 call_inst.getArgOperand(1),
1395 call_inst.getArgOperand(2),
1396 call_inst.getArgOperand(3),
1397 kLong);
1398 return NULL;
1399 }
1400 case IntrinsicHelper::InstanceFieldPutObjectFast: {
1401 Expand_IPutFast(call_inst.getArgOperand(0),
1402 call_inst.getArgOperand(1),
1403 call_inst.getArgOperand(2),
1404 call_inst.getArgOperand(3),
1405 kObject);
1406 return NULL;
1407 }
1408 case IntrinsicHelper::InstanceFieldPutBooleanFast: {
1409 Expand_IPutFast(call_inst.getArgOperand(0),
1410 call_inst.getArgOperand(1),
1411 call_inst.getArgOperand(2),
1412 call_inst.getArgOperand(3),
1413 kBoolean);
1414 return NULL;
1415 }
1416 case IntrinsicHelper::InstanceFieldPutByteFast: {
1417 Expand_IPutFast(call_inst.getArgOperand(0),
1418 call_inst.getArgOperand(1),
1419 call_inst.getArgOperand(2),
1420 call_inst.getArgOperand(3),
1421 kByte);
1422 return NULL;
1423 }
1424 case IntrinsicHelper::InstanceFieldPutCharFast: {
1425 Expand_IPutFast(call_inst.getArgOperand(0),
1426 call_inst.getArgOperand(1),
1427 call_inst.getArgOperand(2),
1428 call_inst.getArgOperand(3),
1429 kChar);
1430 return NULL;
1431 }
1432 case IntrinsicHelper::InstanceFieldPutShortFast: {
1433 Expand_IPutFast(call_inst.getArgOperand(0),
1434 call_inst.getArgOperand(1),
1435 call_inst.getArgOperand(2),
1436 call_inst.getArgOperand(3),
1437 kShort);
1438 return NULL;
1439 }
Logan Chien75e4b602012-07-23 14:24:12 -07001440
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001441 //==- Static Field -----------------------------------------------------==//
1442 case IntrinsicHelper::StaticFieldGet:
1443 case IntrinsicHelper::StaticFieldGetBoolean:
1444 case IntrinsicHelper::StaticFieldGetByte:
1445 case IntrinsicHelper::StaticFieldGetChar:
1446 case IntrinsicHelper::StaticFieldGetShort: {
1447 return ExpandToRuntime(runtime_support::Get32Static, call_inst);
1448 }
1449 case IntrinsicHelper::StaticFieldGetWide: {
1450 return ExpandToRuntime(runtime_support::Get64Static, call_inst);
1451 }
1452 case IntrinsicHelper::StaticFieldGetObject: {
1453 return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
1454 }
1455 case IntrinsicHelper::StaticFieldGetFast: {
1456 return Expand_SGetFast(call_inst.getArgOperand(0),
1457 call_inst.getArgOperand(1),
1458 call_inst.getArgOperand(2),
1459 kInt);
1460 }
1461 case IntrinsicHelper::StaticFieldGetWideFast: {
1462 return Expand_SGetFast(call_inst.getArgOperand(0),
1463 call_inst.getArgOperand(1),
1464 call_inst.getArgOperand(2),
1465 kLong);
1466 }
1467 case IntrinsicHelper::StaticFieldGetObjectFast: {
1468 return Expand_SGetFast(call_inst.getArgOperand(0),
1469 call_inst.getArgOperand(1),
1470 call_inst.getArgOperand(2),
1471 kObject);
1472 }
1473 case IntrinsicHelper::StaticFieldGetBooleanFast: {
1474 return Expand_SGetFast(call_inst.getArgOperand(0),
1475 call_inst.getArgOperand(1),
1476 call_inst.getArgOperand(2),
1477 kBoolean);
1478 }
1479 case IntrinsicHelper::StaticFieldGetByteFast: {
1480 return Expand_SGetFast(call_inst.getArgOperand(0),
1481 call_inst.getArgOperand(1),
1482 call_inst.getArgOperand(2),
1483 kByte);
1484 }
1485 case IntrinsicHelper::StaticFieldGetCharFast: {
1486 return Expand_SGetFast(call_inst.getArgOperand(0),
1487 call_inst.getArgOperand(1),
1488 call_inst.getArgOperand(2),
1489 kChar);
1490 }
1491 case IntrinsicHelper::StaticFieldGetShortFast: {
1492 return Expand_SGetFast(call_inst.getArgOperand(0),
1493 call_inst.getArgOperand(1),
1494 call_inst.getArgOperand(2),
1495 kShort);
1496 }
1497 case IntrinsicHelper::StaticFieldPut:
1498 case IntrinsicHelper::StaticFieldPutBoolean:
1499 case IntrinsicHelper::StaticFieldPutByte:
1500 case IntrinsicHelper::StaticFieldPutChar:
1501 case IntrinsicHelper::StaticFieldPutShort: {
1502 return ExpandToRuntime(runtime_support::Set32Static, call_inst);
1503 }
1504 case IntrinsicHelper::StaticFieldPutWide: {
1505 return ExpandToRuntime(runtime_support::Set64Static, call_inst);
1506 }
1507 case IntrinsicHelper::StaticFieldPutObject: {
1508 return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
1509 }
1510 case IntrinsicHelper::StaticFieldPutFast: {
1511 Expand_SPutFast(call_inst.getArgOperand(0),
1512 call_inst.getArgOperand(1),
1513 call_inst.getArgOperand(2),
1514 call_inst.getArgOperand(3),
1515 kInt);
1516 return NULL;
1517 }
1518 case IntrinsicHelper::StaticFieldPutWideFast: {
1519 Expand_SPutFast(call_inst.getArgOperand(0),
1520 call_inst.getArgOperand(1),
1521 call_inst.getArgOperand(2),
1522 call_inst.getArgOperand(3),
1523 kLong);
1524 return NULL;
1525 }
1526 case IntrinsicHelper::StaticFieldPutObjectFast: {
1527 Expand_SPutFast(call_inst.getArgOperand(0),
1528 call_inst.getArgOperand(1),
1529 call_inst.getArgOperand(2),
1530 call_inst.getArgOperand(3),
1531 kObject);
1532 return NULL;
1533 }
1534 case IntrinsicHelper::StaticFieldPutBooleanFast: {
1535 Expand_SPutFast(call_inst.getArgOperand(0),
1536 call_inst.getArgOperand(1),
1537 call_inst.getArgOperand(2),
1538 call_inst.getArgOperand(3),
1539 kBoolean);
1540 return NULL;
1541 }
1542 case IntrinsicHelper::StaticFieldPutByteFast: {
1543 Expand_SPutFast(call_inst.getArgOperand(0),
1544 call_inst.getArgOperand(1),
1545 call_inst.getArgOperand(2),
1546 call_inst.getArgOperand(3),
1547 kByte);
1548 return NULL;
1549 }
1550 case IntrinsicHelper::StaticFieldPutCharFast: {
1551 Expand_SPutFast(call_inst.getArgOperand(0),
1552 call_inst.getArgOperand(1),
1553 call_inst.getArgOperand(2),
1554 call_inst.getArgOperand(3),
1555 kChar);
1556 return NULL;
1557 }
1558 case IntrinsicHelper::StaticFieldPutShortFast: {
1559 Expand_SPutFast(call_inst.getArgOperand(0),
1560 call_inst.getArgOperand(1),
1561 call_inst.getArgOperand(2),
1562 call_inst.getArgOperand(3),
1563 kShort);
1564 return NULL;
1565 }
1566 case IntrinsicHelper::LoadDeclaringClassSSB: {
1567 return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
1568 }
1569 case IntrinsicHelper::LoadClassSSBFromDexCache: {
1570 return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
1571 }
1572 case IntrinsicHelper::InitializeAndLoadClassSSB: {
1573 return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
1574 }
Logan Chien75e4b602012-07-23 14:24:12 -07001575
1576 //==- High-level Array -------------------------------------------------==//
1577 case IntrinsicHelper::HLArrayGet: {
1578 UNIMPLEMENTED(FATAL);
1579 return NULL;
1580 }
1581 case IntrinsicHelper::HLArrayGetBoolean: {
1582 UNIMPLEMENTED(FATAL);
1583 return NULL;
1584 }
1585 case IntrinsicHelper::HLArrayGetByte: {
1586 UNIMPLEMENTED(FATAL);
1587 return NULL;
1588 }
1589 case IntrinsicHelper::HLArrayGetChar: {
1590 UNIMPLEMENTED(FATAL);
1591 return NULL;
1592 }
1593 case IntrinsicHelper::HLArrayGetShort: {
1594 UNIMPLEMENTED(FATAL);
1595 return NULL;
1596 }
1597 case IntrinsicHelper::HLArrayGetFloat: {
1598 UNIMPLEMENTED(FATAL);
1599 return NULL;
1600 }
1601 case IntrinsicHelper::HLArrayGetWide: {
1602 UNIMPLEMENTED(FATAL);
1603 return NULL;
1604 }
1605 case IntrinsicHelper::HLArrayGetDouble: {
1606 UNIMPLEMENTED(FATAL);
1607 return NULL;
1608 }
1609 case IntrinsicHelper::HLArrayGetObject: {
1610 UNIMPLEMENTED(FATAL);
1611 return NULL;
1612 }
1613 case IntrinsicHelper::HLArrayPut: {
1614 UNIMPLEMENTED(FATAL);
1615 return NULL;
1616 }
1617 case IntrinsicHelper::HLArrayPutBoolean: {
1618 UNIMPLEMENTED(FATAL);
1619 return NULL;
1620 }
1621 case IntrinsicHelper::HLArrayPutByte: {
1622 UNIMPLEMENTED(FATAL);
1623 return NULL;
1624 }
1625 case IntrinsicHelper::HLArrayPutChar: {
1626 UNIMPLEMENTED(FATAL);
1627 return NULL;
1628 }
1629 case IntrinsicHelper::HLArrayPutShort: {
1630 UNIMPLEMENTED(FATAL);
1631 return NULL;
1632 }
1633 case IntrinsicHelper::HLArrayPutFloat: {
1634 UNIMPLEMENTED(FATAL);
1635 return NULL;
1636 }
1637 case IntrinsicHelper::HLArrayPutWide: {
1638 UNIMPLEMENTED(FATAL);
1639 return NULL;
1640 }
1641 case IntrinsicHelper::HLArrayPutDouble: {
1642 UNIMPLEMENTED(FATAL);
1643 return NULL;
1644 }
1645 case IntrinsicHelper::HLArrayPutObject: {
1646 UNIMPLEMENTED(FATAL);
1647 return NULL;
1648 }
1649
1650 //==- High-level Instance ----------------------------------------------==//
1651 case IntrinsicHelper::HLIGet: {
1652 UNIMPLEMENTED(FATAL);
1653 return NULL;
1654 }
1655 case IntrinsicHelper::HLIGetBoolean: {
1656 UNIMPLEMENTED(FATAL);
1657 return NULL;
1658 }
1659 case IntrinsicHelper::HLIGetByte: {
1660 UNIMPLEMENTED(FATAL);
1661 return NULL;
1662 }
1663 case IntrinsicHelper::HLIGetChar: {
1664 UNIMPLEMENTED(FATAL);
1665 return NULL;
1666 }
1667 case IntrinsicHelper::HLIGetShort: {
1668 UNIMPLEMENTED(FATAL);
1669 return NULL;
1670 }
1671 case IntrinsicHelper::HLIGetFloat: {
1672 UNIMPLEMENTED(FATAL);
1673 return NULL;
1674 }
1675 case IntrinsicHelper::HLIGetWide: {
1676 UNIMPLEMENTED(FATAL);
1677 return NULL;
1678 }
1679 case IntrinsicHelper::HLIGetDouble: {
1680 UNIMPLEMENTED(FATAL);
1681 return NULL;
1682 }
1683 case IntrinsicHelper::HLIGetObject: {
1684 UNIMPLEMENTED(FATAL);
1685 return NULL;
1686 }
1687 case IntrinsicHelper::HLIPut: {
1688 UNIMPLEMENTED(FATAL);
1689 return NULL;
1690 }
1691 case IntrinsicHelper::HLIPutBoolean: {
1692 UNIMPLEMENTED(FATAL);
1693 return NULL;
1694 }
1695 case IntrinsicHelper::HLIPutByte: {
1696 UNIMPLEMENTED(FATAL);
1697 return NULL;
1698 }
1699 case IntrinsicHelper::HLIPutChar: {
1700 UNIMPLEMENTED(FATAL);
1701 return NULL;
1702 }
1703 case IntrinsicHelper::HLIPutShort: {
1704 UNIMPLEMENTED(FATAL);
1705 return NULL;
1706 }
1707 case IntrinsicHelper::HLIPutFloat: {
1708 UNIMPLEMENTED(FATAL);
1709 return NULL;
1710 }
1711 case IntrinsicHelper::HLIPutWide: {
1712 UNIMPLEMENTED(FATAL);
1713 return NULL;
1714 }
1715 case IntrinsicHelper::HLIPutDouble: {
1716 UNIMPLEMENTED(FATAL);
1717 return NULL;
1718 }
1719 case IntrinsicHelper::HLIPutObject: {
1720 UNIMPLEMENTED(FATAL);
1721 return NULL;
1722 }
1723
1724 //==- High-level Invoke ------------------------------------------------==//
1725 case IntrinsicHelper::HLInvokeVoid: {
1726 UNIMPLEMENTED(FATAL);
1727 return NULL;
1728 }
1729 case IntrinsicHelper::HLInvokeObj: {
1730 UNIMPLEMENTED(FATAL);
1731 return NULL;
1732 }
1733 case IntrinsicHelper::HLInvokeInt: {
1734 UNIMPLEMENTED(FATAL);
1735 return NULL;
1736 }
1737 case IntrinsicHelper::HLInvokeFloat: {
1738 UNIMPLEMENTED(FATAL);
1739 return NULL;
1740 }
1741 case IntrinsicHelper::HLInvokeLong: {
1742 UNIMPLEMENTED(FATAL);
1743 return NULL;
1744 }
1745 case IntrinsicHelper::HLInvokeDouble: {
1746 UNIMPLEMENTED(FATAL);
1747 return NULL;
1748 }
1749
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001750 //==- Invoke -----------------------------------------------------------==//
1751 case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
1752 return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
1753 }
1754 case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
1755 return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
1756 }
1757 case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
1758 return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
1759 }
1760 case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
1761 return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
1762 }
1763 case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
1764 return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
1765 }
1766 case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
1767 return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
1768 }
1769 case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
1770 return Expand_GetVirtualCalleeMethodObjAddrFast(
1771 call_inst.getArgOperand(0), call_inst.getArgOperand(1));
1772 }
1773 case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
1774 return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
1775 }
1776 case IntrinsicHelper::InvokeRetVoid:
1777 case IntrinsicHelper::InvokeRetBoolean:
1778 case IntrinsicHelper::InvokeRetByte:
1779 case IntrinsicHelper::InvokeRetChar:
1780 case IntrinsicHelper::InvokeRetShort:
1781 case IntrinsicHelper::InvokeRetInt:
1782 case IntrinsicHelper::InvokeRetLong:
1783 case IntrinsicHelper::InvokeRetFloat:
1784 case IntrinsicHelper::InvokeRetDouble:
1785 case IntrinsicHelper::InvokeRetObject: {
1786 return Expand_Invoke(call_inst);
1787 }
Logan Chien75e4b602012-07-23 14:24:12 -07001788
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001789 //==- Math -------------------------------------------------------------==//
1790 case IntrinsicHelper::DivInt: {
1791 return Expand_DivRem(call_inst.getArgOperand(0),
1792 call_inst.getArgOperand(1),
1793 /* is_div */true, kInt);
1794 }
1795 case IntrinsicHelper::RemInt: {
1796 return Expand_DivRem(call_inst.getArgOperand(0),
1797 call_inst.getArgOperand(1),
1798 /* is_div */false, kInt);
1799 }
1800 case IntrinsicHelper::DivLong: {
1801 return Expand_DivRem(call_inst.getArgOperand(0),
1802 call_inst.getArgOperand(1),
1803 /* is_div */true, kLong);
1804 }
1805 case IntrinsicHelper::RemLong: {
1806 return Expand_DivRem(call_inst.getArgOperand(0),
1807 call_inst.getArgOperand(1),
1808 /* is_div */false, kLong);
1809 }
1810 case IntrinsicHelper::D2L: {
1811 return ExpandToRuntime(runtime_support::art_d2l, call_inst);
1812 }
1813 case IntrinsicHelper::D2I: {
1814 return ExpandToRuntime(runtime_support::art_d2i, call_inst);
1815 }
1816 case IntrinsicHelper::F2L: {
1817 return ExpandToRuntime(runtime_support::art_f2l, call_inst);
1818 }
1819 case IntrinsicHelper::F2I: {
1820 return ExpandToRuntime(runtime_support::art_f2i, call_inst);
1821 }
Logan Chien75e4b602012-07-23 14:24:12 -07001822
1823 //==- High-level Static ------------------------------------------------==//
1824 case IntrinsicHelper::HLSget: {
1825 UNIMPLEMENTED(FATAL);
1826 return NULL;
1827 }
1828 case IntrinsicHelper::HLSgetBoolean: {
1829 UNIMPLEMENTED(FATAL);
1830 return NULL;
1831 }
1832 case IntrinsicHelper::HLSgetByte: {
1833 UNIMPLEMENTED(FATAL);
1834 return NULL;
1835 }
1836 case IntrinsicHelper::HLSgetChar: {
1837 UNIMPLEMENTED(FATAL);
1838 return NULL;
1839 }
1840 case IntrinsicHelper::HLSgetShort: {
1841 UNIMPLEMENTED(FATAL);
1842 return NULL;
1843 }
1844 case IntrinsicHelper::HLSgetFloat: {
1845 UNIMPLEMENTED(FATAL);
1846 return NULL;
1847 }
1848 case IntrinsicHelper::HLSgetWide: {
1849 UNIMPLEMENTED(FATAL);
1850 return NULL;
1851 }
1852 case IntrinsicHelper::HLSgetDouble: {
1853 UNIMPLEMENTED(FATAL);
1854 return NULL;
1855 }
1856 case IntrinsicHelper::HLSgetObject: {
1857 UNIMPLEMENTED(FATAL);
1858 return NULL;
1859 }
1860 case IntrinsicHelper::HLSput: {
1861 UNIMPLEMENTED(FATAL);
1862 return NULL;
1863 }
1864 case IntrinsicHelper::HLSputBoolean: {
1865 UNIMPLEMENTED(FATAL);
1866 return NULL;
1867 }
1868 case IntrinsicHelper::HLSputByte: {
1869 UNIMPLEMENTED(FATAL);
1870 return NULL;
1871 }
1872 case IntrinsicHelper::HLSputChar: {
1873 UNIMPLEMENTED(FATAL);
1874 return NULL;
1875 }
1876 case IntrinsicHelper::HLSputShort: {
1877 UNIMPLEMENTED(FATAL);
1878 return NULL;
1879 }
1880 case IntrinsicHelper::HLSputFloat: {
1881 UNIMPLEMENTED(FATAL);
1882 return NULL;
1883 }
1884 case IntrinsicHelper::HLSputWide: {
1885 UNIMPLEMENTED(FATAL);
1886 return NULL;
1887 }
1888 case IntrinsicHelper::HLSputDouble: {
1889 UNIMPLEMENTED(FATAL);
1890 return NULL;
1891 }
1892 case IntrinsicHelper::HLSputObject: {
1893 UNIMPLEMENTED(FATAL);
1894 return NULL;
1895 }
1896
1897 //==- High-level Monitor -----------------------------------------------==//
1898 case IntrinsicHelper::MonitorEnter: {
1899 UNIMPLEMENTED(FATAL);
1900 return NULL;
1901 }
1902 case IntrinsicHelper::MonitorExit: {
1903 UNIMPLEMENTED(FATAL);
1904 return NULL;
1905 }
1906
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001907 //==- Shadow Frame -----------------------------------------------------==//
1908 case IntrinsicHelper::AllocaShadowFrame: {
1909 Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
1910 return NULL;
1911 }
1912 case IntrinsicHelper::SetShadowFrameEntry: {
1913 Expand_SetShadowFrameEntry(call_inst.getArgOperand(0),
1914 call_inst.getArgOperand(1));
1915 return NULL;
1916 }
1917 case IntrinsicHelper::PopShadowFrame: {
1918 Expand_PopShadowFrame();
1919 return NULL;
1920 }
1921 case IntrinsicHelper::UpdateDexPC: {
1922 Expand_UpdateDexPC(call_inst.getArgOperand(0));
1923 return NULL;
1924 }
TDYa127a1b21852012-07-23 03:20:39 -07001925
Logan Chien75e4b602012-07-23 14:24:12 -07001926 //==- Comparison -------------------------------------------------------==//
1927 case IntrinsicHelper::CmplFloat:
1928 case IntrinsicHelper::CmplDouble: {
1929 return Expand_FPCompare(call_inst.getArgOperand(0),
1930 call_inst.getArgOperand(1),
1931 false);
1932 }
1933 case IntrinsicHelper::CmpgFloat:
1934 case IntrinsicHelper::CmpgDouble: {
1935 return Expand_FPCompare(call_inst.getArgOperand(0),
1936 call_inst.getArgOperand(1),
1937 true);
1938 }
1939 case IntrinsicHelper::CmpLong: {
1940 return Expand_LongCompare(call_inst.getArgOperand(0),
1941 call_inst.getArgOperand(1));
1942 }
TDYa127a1b21852012-07-23 03:20:39 -07001943
Logan Chien75e4b602012-07-23 14:24:12 -07001944 //==- Switch -----------------------------------------------------------==//
1945 case greenland::IntrinsicHelper::SparseSwitch: {
1946 UNIMPLEMENTED(FATAL);
1947 return NULL;
1948 }
1949 case greenland::IntrinsicHelper::PackedSwitch: {
1950 UNIMPLEMENTED(FATAL);
1951 return NULL;
1952 }
1953
1954 //==- Const ------------------------------------------------------------==//
Logan Chiend54a23d2012-07-24 11:19:23 -07001955 case greenland::IntrinsicHelper::ConstInt:
Logan Chien75e4b602012-07-23 14:24:12 -07001956 case greenland::IntrinsicHelper::ConstLong: {
Logan Chiend54a23d2012-07-24 11:19:23 -07001957 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07001958 }
1959 case greenland::IntrinsicHelper::ConstFloat: {
Logan Chiend54a23d2012-07-24 11:19:23 -07001960 return irb_.CreateBitCast(call_inst.getArgOperand(0),
1961 irb_.getJFloatTy());
Logan Chien75e4b602012-07-23 14:24:12 -07001962 }
1963 case greenland::IntrinsicHelper::ConstDouble: {
Logan Chiend54a23d2012-07-24 11:19:23 -07001964 return irb_.CreateBitCast(call_inst.getArgOperand(0),
1965 irb_.getJDoubleTy());
1966 }
1967 case greenland::IntrinsicHelper::ConstObj: {
1968 LOG(FATAL) << "ConstObj should not occur at all";
Logan Chien75e4b602012-07-23 14:24:12 -07001969 return NULL;
1970 }
1971
1972 //==- Method Info ------------------------------------------------------==//
1973 case greenland::IntrinsicHelper::MethodInfo: {
1974 UNIMPLEMENTED(FATAL);
1975 return NULL;
1976 }
1977
1978 //==- Copy -------------------------------------------------------------==//
Logan Chiend54a23d2012-07-24 11:19:23 -07001979 case greenland::IntrinsicHelper::CopyInt:
1980 case greenland::IntrinsicHelper::CopyFloat:
1981 case greenland::IntrinsicHelper::CopyLong:
1982 case greenland::IntrinsicHelper::CopyDouble: {
1983 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07001984 }
1985 case greenland::IntrinsicHelper::CopyObj: {
Logan Chiend54a23d2012-07-24 11:19:23 -07001986 // TODO: Update the shadow frame slots.
1987 return call_inst.getArgOperand(0);
Logan Chien75e4b602012-07-23 14:24:12 -07001988 }
1989
1990 //==- Shift ------------------------------------------------------------==//
1991 case greenland::IntrinsicHelper::SHLLong: {
1992 return Expand_IntegerShift(call_inst.getArgOperand(0),
1993 call_inst.getArgOperand(1),
1994 kIntegerSHL, kLong);
1995 }
1996 case greenland::IntrinsicHelper::SHRLong: {
1997 return Expand_IntegerShift(call_inst.getArgOperand(0),
1998 call_inst.getArgOperand(1),
1999 kIntegerSHR, kLong);
2000 }
2001 case greenland::IntrinsicHelper::USHRLong: {
2002 return Expand_IntegerShift(call_inst.getArgOperand(0),
2003 call_inst.getArgOperand(1),
2004 kIntegerUSHR, kLong);
2005 }
2006 case greenland::IntrinsicHelper::SHLInt: {
2007 return Expand_IntegerShift(call_inst.getArgOperand(0),
2008 call_inst.getArgOperand(1),
2009 kIntegerSHL, kInt);
2010 }
2011 case greenland::IntrinsicHelper::SHRInt: {
2012 return Expand_IntegerShift(call_inst.getArgOperand(0),
2013 call_inst.getArgOperand(1),
2014 kIntegerSHR, kInt);
2015 }
2016 case greenland::IntrinsicHelper::USHRInt: {
2017 return Expand_IntegerShift(call_inst.getArgOperand(0),
2018 call_inst.getArgOperand(1),
2019 kIntegerUSHR, kInt);
2020 }
2021
2022 //==- Conversion -------------------------------------------------------==//
TDYa127a1b21852012-07-23 03:20:39 -07002023 case IntrinsicHelper::IntToChar: {
2024 return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
2025 irb_.getJIntTy());
2026 }
2027 case IntrinsicHelper::IntToShort: {
2028 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
2029 irb_.getJIntTy());
2030 }
2031 case IntrinsicHelper::IntToByte: {
2032 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
2033 irb_.getJIntTy());
2034 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002035
Logan Chien75e4b602012-07-23 14:24:12 -07002036 //==- Unknown Cases ----------------------------------------------------==//
2037 case IntrinsicHelper::MaxIntrinsicId:
2038 case IntrinsicHelper::UnknownId:
2039 //default:
2040 // NOTE: "default" is intentionally commented so that C/C++ compiler will
2041 // give some warning on unmatched cases.
2042 // NOTE: We should not implement these cases.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002043 break;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002044 }
Logan Chien75e4b602012-07-23 14:24:12 -07002045 UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002046 return NULL;
2047}
2048
2049} // anonymous namespace
2050
2051namespace art {
2052namespace compiler_llvm {
2053
2054llvm::FunctionPass*
2055CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb) {
2056 return new GBCExpanderPass(intrinsic_helper, irb);
2057}
2058
2059} // namespace compiler_llvm
2060} // namespace art