blob: 8fd6c18737971431b25f7f552dedbc0ad5dc67cc [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 }
1086 case IntrinsicHelper::TestSuspend: {
1087 Expand_TestSuspend(call_inst);
1088 return NULL;
1089 }
Logan Chien75e4b602012-07-23 14:24:12 -07001090 case IntrinsicHelper::CheckSuspend: {
1091 UNIMPLEMENTED(FATAL);
1092 return NULL;
1093 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001094 case IntrinsicHelper::MarkGCCard: {
TDYa1279a129452012-07-19 03:10:08 -07001095 Expand_MarkGCCard(call_inst);
1096 return NULL;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001097 }
Logan Chien75e4b602012-07-23 14:24:12 -07001098
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001099 //==- Exception --------------------------------------------------------==//
1100 case IntrinsicHelper::ThrowException: {
1101 return ExpandToRuntime(runtime_support::ThrowException, call_inst);
1102 }
1103 case IntrinsicHelper::GetException: {
1104 return Expand_GetException();
1105 }
1106 case IntrinsicHelper::IsExceptionPending: {
1107 return irb_.Runtime().EmitIsExceptionPending();
1108 }
1109 case IntrinsicHelper::FindCatchBlock: {
1110 return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
1111 }
1112 case IntrinsicHelper::ThrowDivZeroException: {
1113 return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
1114 }
1115 case IntrinsicHelper::ThrowNullPointerException: {
1116 return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
1117 }
1118 case IntrinsicHelper::ThrowIndexOutOfBounds: {
1119 return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
1120 }
Logan Chien75e4b602012-07-23 14:24:12 -07001121
1122 //==- Const String -----------------------------------------------------==//
1123 case IntrinsicHelper::ConstString: {
1124 UNIMPLEMENTED(FATAL);
1125 return NULL;
1126 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001127 case IntrinsicHelper::LoadStringFromDexCache: {
1128 return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
1129 }
1130 case IntrinsicHelper::ResolveString: {
1131 return ExpandToRuntime(runtime_support::ResolveString, call_inst);
1132 }
Logan Chien75e4b602012-07-23 14:24:12 -07001133
1134 //==- Const Class ------------------------------------------------------==//
1135 case IntrinsicHelper::ConstClass: {
1136 UNIMPLEMENTED(FATAL);
1137 return NULL;
1138 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001139 case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
1140 return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
1141 }
1142 case IntrinsicHelper::LoadTypeFromDexCache: {
1143 return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
1144 }
1145 case IntrinsicHelper::InitializeType: {
1146 return ExpandToRuntime(runtime_support::InitializeType, call_inst);
1147 }
Logan Chien75e4b602012-07-23 14:24:12 -07001148
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001149 //==- Lock -------------------------------------------------------------==//
1150 case IntrinsicHelper::LockObject: {
1151 Expand_LockObject(call_inst.getArgOperand(0));
1152 return NULL;
1153 }
1154 case IntrinsicHelper::UnlockObject: {
1155 Expand_UnlockObject(call_inst.getArgOperand(0));
1156 return NULL;
1157 }
Logan Chien75e4b602012-07-23 14:24:12 -07001158
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001159 //==- Cast -------------------------------------------------------------==//
1160 case IntrinsicHelper::CheckCast: {
1161 return ExpandToRuntime(runtime_support::CheckCast, call_inst);
1162 }
Logan Chien75e4b602012-07-23 14:24:12 -07001163 case IntrinsicHelper::HLCheckCast: {
1164 UNIMPLEMENTED(FATAL);
1165 return NULL;
1166 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001167 case IntrinsicHelper::IsAssignable: {
1168 return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
1169 }
Logan Chien75e4b602012-07-23 14:24:12 -07001170
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001171 //==- Alloc ------------------------------------------------------------==//
1172 case IntrinsicHelper::AllocObject: {
1173 return ExpandToRuntime(runtime_support::AllocObject, call_inst);
1174 }
1175 case IntrinsicHelper::AllocObjectWithAccessCheck: {
1176 return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
1177 }
Logan Chien75e4b602012-07-23 14:24:12 -07001178
1179 //==- Instance ---------------------------------------------------------==//
1180 case IntrinsicHelper::NewInstance: {
1181 UNIMPLEMENTED(FATAL);
1182 return NULL;
1183 }
1184 case IntrinsicHelper::InstanceOf: {
1185 UNIMPLEMENTED(FATAL);
1186 return NULL;
1187 }
1188
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001189 //==- Array ------------------------------------------------------------==//
Logan Chien75e4b602012-07-23 14:24:12 -07001190 case IntrinsicHelper::NewArray: {
1191 UNIMPLEMENTED(FATAL);
1192 return NULL;
1193 }
1194 case IntrinsicHelper::OptArrayLength: {
1195 UNIMPLEMENTED(FATAL);
1196 return NULL;
1197 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001198 case IntrinsicHelper::ArrayLength: {
1199 return EmitLoadArrayLength(call_inst.getArgOperand(0));
1200 }
1201 case IntrinsicHelper::AllocArray: {
1202 return ExpandToRuntime(runtime_support::AllocArray, call_inst);
1203 }
1204 case IntrinsicHelper::AllocArrayWithAccessCheck: {
1205 return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
1206 call_inst);
1207 }
1208 case IntrinsicHelper::CheckAndAllocArray: {
1209 return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
1210 }
1211 case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
1212 return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
1213 call_inst);
1214 }
1215 case IntrinsicHelper::ArrayGet: {
1216 return Expand_ArrayGet(call_inst.getArgOperand(0),
1217 call_inst.getArgOperand(1),
1218 kInt);
1219 }
1220 case IntrinsicHelper::ArrayGetWide: {
1221 return Expand_ArrayGet(call_inst.getArgOperand(0),
1222 call_inst.getArgOperand(1),
1223 kLong);
1224 }
1225 case IntrinsicHelper::ArrayGetObject: {
1226 return Expand_ArrayGet(call_inst.getArgOperand(0),
1227 call_inst.getArgOperand(1),
1228 kObject);
1229 }
1230 case IntrinsicHelper::ArrayGetBoolean: {
1231 return Expand_ArrayGet(call_inst.getArgOperand(0),
1232 call_inst.getArgOperand(1),
1233 kBoolean);
1234 }
1235 case IntrinsicHelper::ArrayGetByte: {
1236 return Expand_ArrayGet(call_inst.getArgOperand(0),
1237 call_inst.getArgOperand(1),
1238 kByte);
1239 }
1240 case IntrinsicHelper::ArrayGetChar: {
1241 return Expand_ArrayGet(call_inst.getArgOperand(0),
1242 call_inst.getArgOperand(1),
1243 kChar);
1244 }
1245 case IntrinsicHelper::ArrayGetShort: {
1246 return Expand_ArrayGet(call_inst.getArgOperand(0),
1247 call_inst.getArgOperand(1),
1248 kShort);
1249 }
1250 case IntrinsicHelper::ArrayPut: {
1251 Expand_ArrayPut(call_inst.getArgOperand(0),
1252 call_inst.getArgOperand(1),
1253 call_inst.getArgOperand(2),
1254 kInt);
1255 return NULL;
1256 }
1257 case IntrinsicHelper::ArrayPutWide: {
1258 Expand_ArrayPut(call_inst.getArgOperand(0),
1259 call_inst.getArgOperand(1),
1260 call_inst.getArgOperand(2),
1261 kLong);
1262 return NULL;
1263 }
1264 case IntrinsicHelper::ArrayPutObject: {
1265 Expand_ArrayPut(call_inst.getArgOperand(0),
1266 call_inst.getArgOperand(1),
1267 call_inst.getArgOperand(2),
1268 kObject);
1269 return NULL;
1270 }
1271 case IntrinsicHelper::ArrayPutBoolean: {
1272 Expand_ArrayPut(call_inst.getArgOperand(0),
1273 call_inst.getArgOperand(1),
1274 call_inst.getArgOperand(2),
1275 kBoolean);
1276 return NULL;
1277 }
1278 case IntrinsicHelper::ArrayPutByte: {
1279 Expand_ArrayPut(call_inst.getArgOperand(0),
1280 call_inst.getArgOperand(1),
1281 call_inst.getArgOperand(2),
1282 kByte);
1283 return NULL;
1284 }
1285 case IntrinsicHelper::ArrayPutChar: {
1286 Expand_ArrayPut(call_inst.getArgOperand(0),
1287 call_inst.getArgOperand(1),
1288 call_inst.getArgOperand(2),
1289 kChar);
1290 return NULL;
1291 }
1292 case IntrinsicHelper::ArrayPutShort: {
1293 Expand_ArrayPut(call_inst.getArgOperand(0),
1294 call_inst.getArgOperand(1),
1295 call_inst.getArgOperand(2),
1296 kShort);
1297 return NULL;
1298 }
1299 case IntrinsicHelper::CheckPutArrayElement: {
1300 return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
1301 }
1302 case IntrinsicHelper::FilledNewArray: {
1303 Expand_FilledNewArray(call_inst);
1304 return NULL;
1305 }
1306 case IntrinsicHelper::FillArrayData: {
1307 return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
1308 }
Logan Chien75e4b602012-07-23 14:24:12 -07001309 case IntrinsicHelper::HLFillArrayData: {
1310 UNIMPLEMENTED(FATAL);
1311 return NULL;
1312 }
1313 case IntrinsicHelper::HLFilledNewArray: {
1314 UNIMPLEMENTED(FATAL);
1315 return NULL;
1316 }
1317
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001318 //==- Instance Field ---------------------------------------------------==//
1319 case IntrinsicHelper::InstanceFieldGet:
1320 case IntrinsicHelper::InstanceFieldGetBoolean:
1321 case IntrinsicHelper::InstanceFieldGetByte:
1322 case IntrinsicHelper::InstanceFieldGetChar:
1323 case IntrinsicHelper::InstanceFieldGetShort: {
1324 return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
1325 }
1326 case IntrinsicHelper::InstanceFieldGetWide: {
1327 return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
1328 }
1329 case IntrinsicHelper::InstanceFieldGetObject: {
1330 return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
1331 }
1332 case IntrinsicHelper::InstanceFieldGetFast: {
1333 return Expand_IGetFast(call_inst.getArgOperand(0),
1334 call_inst.getArgOperand(1),
1335 call_inst.getArgOperand(2),
1336 kInt);
1337 }
1338 case IntrinsicHelper::InstanceFieldGetWideFast: {
1339 return Expand_IGetFast(call_inst.getArgOperand(0),
1340 call_inst.getArgOperand(1),
1341 call_inst.getArgOperand(2),
1342 kLong);
1343 }
1344 case IntrinsicHelper::InstanceFieldGetObjectFast: {
1345 return Expand_IGetFast(call_inst.getArgOperand(0),
1346 call_inst.getArgOperand(1),
1347 call_inst.getArgOperand(2),
1348 kObject);
1349 }
1350 case IntrinsicHelper::InstanceFieldGetBooleanFast: {
1351 return Expand_IGetFast(call_inst.getArgOperand(0),
1352 call_inst.getArgOperand(1),
1353 call_inst.getArgOperand(2),
1354 kBoolean);
1355 }
1356 case IntrinsicHelper::InstanceFieldGetByteFast: {
1357 return Expand_IGetFast(call_inst.getArgOperand(0),
1358 call_inst.getArgOperand(1),
1359 call_inst.getArgOperand(2),
1360 kByte);
1361 }
1362 case IntrinsicHelper::InstanceFieldGetCharFast: {
1363 return Expand_IGetFast(call_inst.getArgOperand(0),
1364 call_inst.getArgOperand(1),
1365 call_inst.getArgOperand(2),
1366 kChar);
1367 }
1368 case IntrinsicHelper::InstanceFieldGetShortFast: {
1369 return Expand_IGetFast(call_inst.getArgOperand(0),
1370 call_inst.getArgOperand(1),
1371 call_inst.getArgOperand(2),
1372 kShort);
1373 }
1374 case IntrinsicHelper::InstanceFieldPut:
1375 case IntrinsicHelper::InstanceFieldPutBoolean:
1376 case IntrinsicHelper::InstanceFieldPutByte:
1377 case IntrinsicHelper::InstanceFieldPutChar:
1378 case IntrinsicHelper::InstanceFieldPutShort: {
1379 return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
1380 }
1381 case IntrinsicHelper::InstanceFieldPutWide: {
1382 return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
1383 }
1384 case IntrinsicHelper::InstanceFieldPutObject: {
1385 return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
1386 }
1387 case IntrinsicHelper::InstanceFieldPutFast: {
1388 Expand_IPutFast(call_inst.getArgOperand(0),
1389 call_inst.getArgOperand(1),
1390 call_inst.getArgOperand(2),
1391 call_inst.getArgOperand(3),
1392 kInt);
1393 return NULL;
1394 }
1395 case IntrinsicHelper::InstanceFieldPutWideFast: {
1396 Expand_IPutFast(call_inst.getArgOperand(0),
1397 call_inst.getArgOperand(1),
1398 call_inst.getArgOperand(2),
1399 call_inst.getArgOperand(3),
1400 kLong);
1401 return NULL;
1402 }
1403 case IntrinsicHelper::InstanceFieldPutObjectFast: {
1404 Expand_IPutFast(call_inst.getArgOperand(0),
1405 call_inst.getArgOperand(1),
1406 call_inst.getArgOperand(2),
1407 call_inst.getArgOperand(3),
1408 kObject);
1409 return NULL;
1410 }
1411 case IntrinsicHelper::InstanceFieldPutBooleanFast: {
1412 Expand_IPutFast(call_inst.getArgOperand(0),
1413 call_inst.getArgOperand(1),
1414 call_inst.getArgOperand(2),
1415 call_inst.getArgOperand(3),
1416 kBoolean);
1417 return NULL;
1418 }
1419 case IntrinsicHelper::InstanceFieldPutByteFast: {
1420 Expand_IPutFast(call_inst.getArgOperand(0),
1421 call_inst.getArgOperand(1),
1422 call_inst.getArgOperand(2),
1423 call_inst.getArgOperand(3),
1424 kByte);
1425 return NULL;
1426 }
1427 case IntrinsicHelper::InstanceFieldPutCharFast: {
1428 Expand_IPutFast(call_inst.getArgOperand(0),
1429 call_inst.getArgOperand(1),
1430 call_inst.getArgOperand(2),
1431 call_inst.getArgOperand(3),
1432 kChar);
1433 return NULL;
1434 }
1435 case IntrinsicHelper::InstanceFieldPutShortFast: {
1436 Expand_IPutFast(call_inst.getArgOperand(0),
1437 call_inst.getArgOperand(1),
1438 call_inst.getArgOperand(2),
1439 call_inst.getArgOperand(3),
1440 kShort);
1441 return NULL;
1442 }
Logan Chien75e4b602012-07-23 14:24:12 -07001443
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001444 //==- Static Field -----------------------------------------------------==//
1445 case IntrinsicHelper::StaticFieldGet:
1446 case IntrinsicHelper::StaticFieldGetBoolean:
1447 case IntrinsicHelper::StaticFieldGetByte:
1448 case IntrinsicHelper::StaticFieldGetChar:
1449 case IntrinsicHelper::StaticFieldGetShort: {
1450 return ExpandToRuntime(runtime_support::Get32Static, call_inst);
1451 }
1452 case IntrinsicHelper::StaticFieldGetWide: {
1453 return ExpandToRuntime(runtime_support::Get64Static, call_inst);
1454 }
1455 case IntrinsicHelper::StaticFieldGetObject: {
1456 return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
1457 }
1458 case IntrinsicHelper::StaticFieldGetFast: {
1459 return Expand_SGetFast(call_inst.getArgOperand(0),
1460 call_inst.getArgOperand(1),
1461 call_inst.getArgOperand(2),
1462 kInt);
1463 }
1464 case IntrinsicHelper::StaticFieldGetWideFast: {
1465 return Expand_SGetFast(call_inst.getArgOperand(0),
1466 call_inst.getArgOperand(1),
1467 call_inst.getArgOperand(2),
1468 kLong);
1469 }
1470 case IntrinsicHelper::StaticFieldGetObjectFast: {
1471 return Expand_SGetFast(call_inst.getArgOperand(0),
1472 call_inst.getArgOperand(1),
1473 call_inst.getArgOperand(2),
1474 kObject);
1475 }
1476 case IntrinsicHelper::StaticFieldGetBooleanFast: {
1477 return Expand_SGetFast(call_inst.getArgOperand(0),
1478 call_inst.getArgOperand(1),
1479 call_inst.getArgOperand(2),
1480 kBoolean);
1481 }
1482 case IntrinsicHelper::StaticFieldGetByteFast: {
1483 return Expand_SGetFast(call_inst.getArgOperand(0),
1484 call_inst.getArgOperand(1),
1485 call_inst.getArgOperand(2),
1486 kByte);
1487 }
1488 case IntrinsicHelper::StaticFieldGetCharFast: {
1489 return Expand_SGetFast(call_inst.getArgOperand(0),
1490 call_inst.getArgOperand(1),
1491 call_inst.getArgOperand(2),
1492 kChar);
1493 }
1494 case IntrinsicHelper::StaticFieldGetShortFast: {
1495 return Expand_SGetFast(call_inst.getArgOperand(0),
1496 call_inst.getArgOperand(1),
1497 call_inst.getArgOperand(2),
1498 kShort);
1499 }
1500 case IntrinsicHelper::StaticFieldPut:
1501 case IntrinsicHelper::StaticFieldPutBoolean:
1502 case IntrinsicHelper::StaticFieldPutByte:
1503 case IntrinsicHelper::StaticFieldPutChar:
1504 case IntrinsicHelper::StaticFieldPutShort: {
1505 return ExpandToRuntime(runtime_support::Set32Static, call_inst);
1506 }
1507 case IntrinsicHelper::StaticFieldPutWide: {
1508 return ExpandToRuntime(runtime_support::Set64Static, call_inst);
1509 }
1510 case IntrinsicHelper::StaticFieldPutObject: {
1511 return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
1512 }
1513 case IntrinsicHelper::StaticFieldPutFast: {
1514 Expand_SPutFast(call_inst.getArgOperand(0),
1515 call_inst.getArgOperand(1),
1516 call_inst.getArgOperand(2),
1517 call_inst.getArgOperand(3),
1518 kInt);
1519 return NULL;
1520 }
1521 case IntrinsicHelper::StaticFieldPutWideFast: {
1522 Expand_SPutFast(call_inst.getArgOperand(0),
1523 call_inst.getArgOperand(1),
1524 call_inst.getArgOperand(2),
1525 call_inst.getArgOperand(3),
1526 kLong);
1527 return NULL;
1528 }
1529 case IntrinsicHelper::StaticFieldPutObjectFast: {
1530 Expand_SPutFast(call_inst.getArgOperand(0),
1531 call_inst.getArgOperand(1),
1532 call_inst.getArgOperand(2),
1533 call_inst.getArgOperand(3),
1534 kObject);
1535 return NULL;
1536 }
1537 case IntrinsicHelper::StaticFieldPutBooleanFast: {
1538 Expand_SPutFast(call_inst.getArgOperand(0),
1539 call_inst.getArgOperand(1),
1540 call_inst.getArgOperand(2),
1541 call_inst.getArgOperand(3),
1542 kBoolean);
1543 return NULL;
1544 }
1545 case IntrinsicHelper::StaticFieldPutByteFast: {
1546 Expand_SPutFast(call_inst.getArgOperand(0),
1547 call_inst.getArgOperand(1),
1548 call_inst.getArgOperand(2),
1549 call_inst.getArgOperand(3),
1550 kByte);
1551 return NULL;
1552 }
1553 case IntrinsicHelper::StaticFieldPutCharFast: {
1554 Expand_SPutFast(call_inst.getArgOperand(0),
1555 call_inst.getArgOperand(1),
1556 call_inst.getArgOperand(2),
1557 call_inst.getArgOperand(3),
1558 kChar);
1559 return NULL;
1560 }
1561 case IntrinsicHelper::StaticFieldPutShortFast: {
1562 Expand_SPutFast(call_inst.getArgOperand(0),
1563 call_inst.getArgOperand(1),
1564 call_inst.getArgOperand(2),
1565 call_inst.getArgOperand(3),
1566 kShort);
1567 return NULL;
1568 }
1569 case IntrinsicHelper::LoadDeclaringClassSSB: {
1570 return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
1571 }
1572 case IntrinsicHelper::LoadClassSSBFromDexCache: {
1573 return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
1574 }
1575 case IntrinsicHelper::InitializeAndLoadClassSSB: {
1576 return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
1577 }
Logan Chien75e4b602012-07-23 14:24:12 -07001578
1579 //==- High-level Array -------------------------------------------------==//
1580 case IntrinsicHelper::HLArrayGet: {
1581 UNIMPLEMENTED(FATAL);
1582 return NULL;
1583 }
1584 case IntrinsicHelper::HLArrayGetBoolean: {
1585 UNIMPLEMENTED(FATAL);
1586 return NULL;
1587 }
1588 case IntrinsicHelper::HLArrayGetByte: {
1589 UNIMPLEMENTED(FATAL);
1590 return NULL;
1591 }
1592 case IntrinsicHelper::HLArrayGetChar: {
1593 UNIMPLEMENTED(FATAL);
1594 return NULL;
1595 }
1596 case IntrinsicHelper::HLArrayGetShort: {
1597 UNIMPLEMENTED(FATAL);
1598 return NULL;
1599 }
1600 case IntrinsicHelper::HLArrayGetFloat: {
1601 UNIMPLEMENTED(FATAL);
1602 return NULL;
1603 }
1604 case IntrinsicHelper::HLArrayGetWide: {
1605 UNIMPLEMENTED(FATAL);
1606 return NULL;
1607 }
1608 case IntrinsicHelper::HLArrayGetDouble: {
1609 UNIMPLEMENTED(FATAL);
1610 return NULL;
1611 }
1612 case IntrinsicHelper::HLArrayGetObject: {
1613 UNIMPLEMENTED(FATAL);
1614 return NULL;
1615 }
1616 case IntrinsicHelper::HLArrayPut: {
1617 UNIMPLEMENTED(FATAL);
1618 return NULL;
1619 }
1620 case IntrinsicHelper::HLArrayPutBoolean: {
1621 UNIMPLEMENTED(FATAL);
1622 return NULL;
1623 }
1624 case IntrinsicHelper::HLArrayPutByte: {
1625 UNIMPLEMENTED(FATAL);
1626 return NULL;
1627 }
1628 case IntrinsicHelper::HLArrayPutChar: {
1629 UNIMPLEMENTED(FATAL);
1630 return NULL;
1631 }
1632 case IntrinsicHelper::HLArrayPutShort: {
1633 UNIMPLEMENTED(FATAL);
1634 return NULL;
1635 }
1636 case IntrinsicHelper::HLArrayPutFloat: {
1637 UNIMPLEMENTED(FATAL);
1638 return NULL;
1639 }
1640 case IntrinsicHelper::HLArrayPutWide: {
1641 UNIMPLEMENTED(FATAL);
1642 return NULL;
1643 }
1644 case IntrinsicHelper::HLArrayPutDouble: {
1645 UNIMPLEMENTED(FATAL);
1646 return NULL;
1647 }
1648 case IntrinsicHelper::HLArrayPutObject: {
1649 UNIMPLEMENTED(FATAL);
1650 return NULL;
1651 }
1652
1653 //==- High-level Instance ----------------------------------------------==//
1654 case IntrinsicHelper::HLIGet: {
1655 UNIMPLEMENTED(FATAL);
1656 return NULL;
1657 }
1658 case IntrinsicHelper::HLIGetBoolean: {
1659 UNIMPLEMENTED(FATAL);
1660 return NULL;
1661 }
1662 case IntrinsicHelper::HLIGetByte: {
1663 UNIMPLEMENTED(FATAL);
1664 return NULL;
1665 }
1666 case IntrinsicHelper::HLIGetChar: {
1667 UNIMPLEMENTED(FATAL);
1668 return NULL;
1669 }
1670 case IntrinsicHelper::HLIGetShort: {
1671 UNIMPLEMENTED(FATAL);
1672 return NULL;
1673 }
1674 case IntrinsicHelper::HLIGetFloat: {
1675 UNIMPLEMENTED(FATAL);
1676 return NULL;
1677 }
1678 case IntrinsicHelper::HLIGetWide: {
1679 UNIMPLEMENTED(FATAL);
1680 return NULL;
1681 }
1682 case IntrinsicHelper::HLIGetDouble: {
1683 UNIMPLEMENTED(FATAL);
1684 return NULL;
1685 }
1686 case IntrinsicHelper::HLIGetObject: {
1687 UNIMPLEMENTED(FATAL);
1688 return NULL;
1689 }
1690 case IntrinsicHelper::HLIPut: {
1691 UNIMPLEMENTED(FATAL);
1692 return NULL;
1693 }
1694 case IntrinsicHelper::HLIPutBoolean: {
1695 UNIMPLEMENTED(FATAL);
1696 return NULL;
1697 }
1698 case IntrinsicHelper::HLIPutByte: {
1699 UNIMPLEMENTED(FATAL);
1700 return NULL;
1701 }
1702 case IntrinsicHelper::HLIPutChar: {
1703 UNIMPLEMENTED(FATAL);
1704 return NULL;
1705 }
1706 case IntrinsicHelper::HLIPutShort: {
1707 UNIMPLEMENTED(FATAL);
1708 return NULL;
1709 }
1710 case IntrinsicHelper::HLIPutFloat: {
1711 UNIMPLEMENTED(FATAL);
1712 return NULL;
1713 }
1714 case IntrinsicHelper::HLIPutWide: {
1715 UNIMPLEMENTED(FATAL);
1716 return NULL;
1717 }
1718 case IntrinsicHelper::HLIPutDouble: {
1719 UNIMPLEMENTED(FATAL);
1720 return NULL;
1721 }
1722 case IntrinsicHelper::HLIPutObject: {
1723 UNIMPLEMENTED(FATAL);
1724 return NULL;
1725 }
1726
1727 //==- High-level Invoke ------------------------------------------------==//
1728 case IntrinsicHelper::HLInvokeVoid: {
1729 UNIMPLEMENTED(FATAL);
1730 return NULL;
1731 }
1732 case IntrinsicHelper::HLInvokeObj: {
1733 UNIMPLEMENTED(FATAL);
1734 return NULL;
1735 }
1736 case IntrinsicHelper::HLInvokeInt: {
1737 UNIMPLEMENTED(FATAL);
1738 return NULL;
1739 }
1740 case IntrinsicHelper::HLInvokeFloat: {
1741 UNIMPLEMENTED(FATAL);
1742 return NULL;
1743 }
1744 case IntrinsicHelper::HLInvokeLong: {
1745 UNIMPLEMENTED(FATAL);
1746 return NULL;
1747 }
1748 case IntrinsicHelper::HLInvokeDouble: {
1749 UNIMPLEMENTED(FATAL);
1750 return NULL;
1751 }
1752
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001753 //==- Invoke -----------------------------------------------------------==//
1754 case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
1755 return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
1756 }
1757 case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
1758 return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
1759 }
1760 case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
1761 return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
1762 }
1763 case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
1764 return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
1765 }
1766 case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
1767 return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
1768 }
1769 case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
1770 return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
1771 }
1772 case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
1773 return Expand_GetVirtualCalleeMethodObjAddrFast(
1774 call_inst.getArgOperand(0), call_inst.getArgOperand(1));
1775 }
1776 case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
1777 return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
1778 }
1779 case IntrinsicHelper::InvokeRetVoid:
1780 case IntrinsicHelper::InvokeRetBoolean:
1781 case IntrinsicHelper::InvokeRetByte:
1782 case IntrinsicHelper::InvokeRetChar:
1783 case IntrinsicHelper::InvokeRetShort:
1784 case IntrinsicHelper::InvokeRetInt:
1785 case IntrinsicHelper::InvokeRetLong:
1786 case IntrinsicHelper::InvokeRetFloat:
1787 case IntrinsicHelper::InvokeRetDouble:
1788 case IntrinsicHelper::InvokeRetObject: {
1789 return Expand_Invoke(call_inst);
1790 }
Logan Chien75e4b602012-07-23 14:24:12 -07001791
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001792 //==- Math -------------------------------------------------------------==//
1793 case IntrinsicHelper::DivInt: {
1794 return Expand_DivRem(call_inst.getArgOperand(0),
1795 call_inst.getArgOperand(1),
1796 /* is_div */true, kInt);
1797 }
1798 case IntrinsicHelper::RemInt: {
1799 return Expand_DivRem(call_inst.getArgOperand(0),
1800 call_inst.getArgOperand(1),
1801 /* is_div */false, kInt);
1802 }
1803 case IntrinsicHelper::DivLong: {
1804 return Expand_DivRem(call_inst.getArgOperand(0),
1805 call_inst.getArgOperand(1),
1806 /* is_div */true, kLong);
1807 }
1808 case IntrinsicHelper::RemLong: {
1809 return Expand_DivRem(call_inst.getArgOperand(0),
1810 call_inst.getArgOperand(1),
1811 /* is_div */false, kLong);
1812 }
1813 case IntrinsicHelper::D2L: {
1814 return ExpandToRuntime(runtime_support::art_d2l, call_inst);
1815 }
1816 case IntrinsicHelper::D2I: {
1817 return ExpandToRuntime(runtime_support::art_d2i, call_inst);
1818 }
1819 case IntrinsicHelper::F2L: {
1820 return ExpandToRuntime(runtime_support::art_f2l, call_inst);
1821 }
1822 case IntrinsicHelper::F2I: {
1823 return ExpandToRuntime(runtime_support::art_f2i, call_inst);
1824 }
Logan Chien75e4b602012-07-23 14:24:12 -07001825
1826 //==- High-level Static ------------------------------------------------==//
1827 case IntrinsicHelper::HLSget: {
1828 UNIMPLEMENTED(FATAL);
1829 return NULL;
1830 }
1831 case IntrinsicHelper::HLSgetBoolean: {
1832 UNIMPLEMENTED(FATAL);
1833 return NULL;
1834 }
1835 case IntrinsicHelper::HLSgetByte: {
1836 UNIMPLEMENTED(FATAL);
1837 return NULL;
1838 }
1839 case IntrinsicHelper::HLSgetChar: {
1840 UNIMPLEMENTED(FATAL);
1841 return NULL;
1842 }
1843 case IntrinsicHelper::HLSgetShort: {
1844 UNIMPLEMENTED(FATAL);
1845 return NULL;
1846 }
1847 case IntrinsicHelper::HLSgetFloat: {
1848 UNIMPLEMENTED(FATAL);
1849 return NULL;
1850 }
1851 case IntrinsicHelper::HLSgetWide: {
1852 UNIMPLEMENTED(FATAL);
1853 return NULL;
1854 }
1855 case IntrinsicHelper::HLSgetDouble: {
1856 UNIMPLEMENTED(FATAL);
1857 return NULL;
1858 }
1859 case IntrinsicHelper::HLSgetObject: {
1860 UNIMPLEMENTED(FATAL);
1861 return NULL;
1862 }
1863 case IntrinsicHelper::HLSput: {
1864 UNIMPLEMENTED(FATAL);
1865 return NULL;
1866 }
1867 case IntrinsicHelper::HLSputBoolean: {
1868 UNIMPLEMENTED(FATAL);
1869 return NULL;
1870 }
1871 case IntrinsicHelper::HLSputByte: {
1872 UNIMPLEMENTED(FATAL);
1873 return NULL;
1874 }
1875 case IntrinsicHelper::HLSputChar: {
1876 UNIMPLEMENTED(FATAL);
1877 return NULL;
1878 }
1879 case IntrinsicHelper::HLSputShort: {
1880 UNIMPLEMENTED(FATAL);
1881 return NULL;
1882 }
1883 case IntrinsicHelper::HLSputFloat: {
1884 UNIMPLEMENTED(FATAL);
1885 return NULL;
1886 }
1887 case IntrinsicHelper::HLSputWide: {
1888 UNIMPLEMENTED(FATAL);
1889 return NULL;
1890 }
1891 case IntrinsicHelper::HLSputDouble: {
1892 UNIMPLEMENTED(FATAL);
1893 return NULL;
1894 }
1895 case IntrinsicHelper::HLSputObject: {
1896 UNIMPLEMENTED(FATAL);
1897 return NULL;
1898 }
1899
1900 //==- High-level Monitor -----------------------------------------------==//
1901 case IntrinsicHelper::MonitorEnter: {
1902 UNIMPLEMENTED(FATAL);
1903 return NULL;
1904 }
1905 case IntrinsicHelper::MonitorExit: {
1906 UNIMPLEMENTED(FATAL);
1907 return NULL;
1908 }
1909
Shih-wei Liao21d28f52012-06-12 05:55:00 -07001910 //==- Shadow Frame -----------------------------------------------------==//
1911 case IntrinsicHelper::AllocaShadowFrame: {
1912 Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
1913 return NULL;
1914 }
1915 case IntrinsicHelper::SetShadowFrameEntry: {
1916 Expand_SetShadowFrameEntry(call_inst.getArgOperand(0),
1917 call_inst.getArgOperand(1));
1918 return NULL;
1919 }
1920 case IntrinsicHelper::PopShadowFrame: {
1921 Expand_PopShadowFrame();
1922 return NULL;
1923 }
1924 case IntrinsicHelper::UpdateDexPC: {
1925 Expand_UpdateDexPC(call_inst.getArgOperand(0));
1926 return NULL;
1927 }
TDYa127a1b21852012-07-23 03:20:39 -07001928
Logan Chien75e4b602012-07-23 14:24:12 -07001929 //==- Comparison -------------------------------------------------------==//
1930 case IntrinsicHelper::CmplFloat:
1931 case IntrinsicHelper::CmplDouble: {
1932 return Expand_FPCompare(call_inst.getArgOperand(0),
1933 call_inst.getArgOperand(1),
1934 false);
1935 }
1936 case IntrinsicHelper::CmpgFloat:
1937 case IntrinsicHelper::CmpgDouble: {
1938 return Expand_FPCompare(call_inst.getArgOperand(0),
1939 call_inst.getArgOperand(1),
1940 true);
1941 }
1942 case IntrinsicHelper::CmpLong: {
1943 return Expand_LongCompare(call_inst.getArgOperand(0),
1944 call_inst.getArgOperand(1));
1945 }
TDYa127a1b21852012-07-23 03:20:39 -07001946
Logan Chien75e4b602012-07-23 14:24:12 -07001947 //==- Switch -----------------------------------------------------------==//
1948 case greenland::IntrinsicHelper::SparseSwitch: {
1949 UNIMPLEMENTED(FATAL);
1950 return NULL;
1951 }
1952 case greenland::IntrinsicHelper::PackedSwitch: {
1953 UNIMPLEMENTED(FATAL);
1954 return NULL;
1955 }
1956
1957 //==- Const ------------------------------------------------------------==//
1958 case greenland::IntrinsicHelper::ConstInt: {
1959 UNIMPLEMENTED(FATAL);
1960 return NULL;
1961 }
1962 case greenland::IntrinsicHelper::ConstObj: {
1963 UNIMPLEMENTED(FATAL);
1964 return NULL;
1965 }
1966 case greenland::IntrinsicHelper::ConstLong: {
1967 UNIMPLEMENTED(FATAL);
1968 return NULL;
1969 }
1970 case greenland::IntrinsicHelper::ConstFloat: {
1971 UNIMPLEMENTED(FATAL);
1972 return NULL;
1973 }
1974 case greenland::IntrinsicHelper::ConstDouble: {
1975 UNIMPLEMENTED(FATAL);
1976 return NULL;
1977 }
1978
1979 //==- Method Info ------------------------------------------------------==//
1980 case greenland::IntrinsicHelper::MethodInfo: {
1981 UNIMPLEMENTED(FATAL);
1982 return NULL;
1983 }
1984
1985 //==- Copy -------------------------------------------------------------==//
1986 case greenland::IntrinsicHelper::CopyInt: {
1987 UNIMPLEMENTED(FATAL);
1988 return NULL;
1989 }
1990 case greenland::IntrinsicHelper::CopyObj: {
1991 UNIMPLEMENTED(FATAL);
1992 return NULL;
1993 }
1994 case greenland::IntrinsicHelper::CopyFloat: {
1995 UNIMPLEMENTED(FATAL);
1996 return NULL;
1997 }
1998 case greenland::IntrinsicHelper::CopyLong: {
1999 UNIMPLEMENTED(FATAL);
2000 return NULL;
2001 }
2002 case greenland::IntrinsicHelper::CopyDouble: {
2003 UNIMPLEMENTED(FATAL);
2004 return NULL;
2005 }
2006
2007 //==- Shift ------------------------------------------------------------==//
2008 case greenland::IntrinsicHelper::SHLLong: {
2009 return Expand_IntegerShift(call_inst.getArgOperand(0),
2010 call_inst.getArgOperand(1),
2011 kIntegerSHL, kLong);
2012 }
2013 case greenland::IntrinsicHelper::SHRLong: {
2014 return Expand_IntegerShift(call_inst.getArgOperand(0),
2015 call_inst.getArgOperand(1),
2016 kIntegerSHR, kLong);
2017 }
2018 case greenland::IntrinsicHelper::USHRLong: {
2019 return Expand_IntegerShift(call_inst.getArgOperand(0),
2020 call_inst.getArgOperand(1),
2021 kIntegerUSHR, kLong);
2022 }
2023 case greenland::IntrinsicHelper::SHLInt: {
2024 return Expand_IntegerShift(call_inst.getArgOperand(0),
2025 call_inst.getArgOperand(1),
2026 kIntegerSHL, kInt);
2027 }
2028 case greenland::IntrinsicHelper::SHRInt: {
2029 return Expand_IntegerShift(call_inst.getArgOperand(0),
2030 call_inst.getArgOperand(1),
2031 kIntegerSHR, kInt);
2032 }
2033 case greenland::IntrinsicHelper::USHRInt: {
2034 return Expand_IntegerShift(call_inst.getArgOperand(0),
2035 call_inst.getArgOperand(1),
2036 kIntegerUSHR, kInt);
2037 }
2038
2039 //==- Conversion -------------------------------------------------------==//
TDYa127a1b21852012-07-23 03:20:39 -07002040 case IntrinsicHelper::IntToChar: {
2041 return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
2042 irb_.getJIntTy());
2043 }
2044 case IntrinsicHelper::IntToShort: {
2045 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
2046 irb_.getJIntTy());
2047 }
2048 case IntrinsicHelper::IntToByte: {
2049 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
2050 irb_.getJIntTy());
2051 }
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002052
Logan Chien75e4b602012-07-23 14:24:12 -07002053 //==- Unknown Cases ----------------------------------------------------==//
2054 case IntrinsicHelper::MaxIntrinsicId:
2055 case IntrinsicHelper::UnknownId:
2056 //default:
2057 // NOTE: "default" is intentionally commented so that C/C++ compiler will
2058 // give some warning on unmatched cases.
2059 // NOTE: We should not implement these cases.
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002060 break;
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002061 }
Logan Chien75e4b602012-07-23 14:24:12 -07002062 UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
Shih-wei Liao21d28f52012-06-12 05:55:00 -07002063 return NULL;
2064}
2065
2066} // anonymous namespace
2067
2068namespace art {
2069namespace compiler_llvm {
2070
2071llvm::FunctionPass*
2072CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb) {
2073 return new GBCExpanderPass(intrinsic_helper, irb);
2074}
2075
2076} // namespace compiler_llvm
2077} // namespace art