blob: e2b98345e57124252612227e04a616f29365dae5 [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 //----------------------------------------------------------------------------
54 // Helper function for GBC expansion
55 //----------------------------------------------------------------------------
56
57 // Split the basic block containing INST at INST and insert a sequence of
58 // basic blocks with a single entry at BEGIN_BB and a single exit at END_BB
59 // before INST.
60 llvm::BasicBlock*
61 SplitAndInsertBasicBlocksAfter(llvm::BasicBlock::iterator inst,
62 llvm::BasicBlock* begin_bb,
63 llvm::BasicBlock* end_bb);
64
65 llvm::Value* ExpandToRuntime(runtime_support::RuntimeId rt,
66 llvm::CallInst& inst);
67
68 private:
69 // TODO: Almost all Emit* are directly copy-n-paste from MethodCompiler.
70 // Refactor these utility functions from MethodCompiler to avoid forking.
71
72 bool EmitStackOverflowCheck(llvm::Instruction* first_non_alloca);
73
74 //----------------------------------------------------------------------------
75 // Dex cache code generation helper function
76 //----------------------------------------------------------------------------
77 llvm::Value* EmitLoadDexCacheAddr(MemberOffset dex_cache_offset);
78
79 llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
80
81 llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
82
83 llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
84
85 llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
86
87 //----------------------------------------------------------------------------
88 // Code generation helper function
89 //----------------------------------------------------------------------------
90 llvm::Value* EmitLoadMethodObjectAddr();
91
92 llvm::Value* EmitLoadArrayLength(llvm::Value* array);
93
94 llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
95
96 llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
97 llvm::Value* this_addr);
98
99 llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
100 llvm::Value* index_value,
101 JType elem_jty);
102
103 private:
104 //----------------------------------------------------------------------------
105 // Expand Greenland intrinsics
106 //----------------------------------------------------------------------------
107 void Expand_TestSuspend(llvm::CallInst& call_inst);
108
109 llvm::Value* Expand_GetException();
110
111 llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
112
113 llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
114
115 void Expand_LockObject(llvm::Value* obj);
116
117 void Expand_UnlockObject(llvm::Value* obj);
118
119 llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
120 llvm::Value* index_value,
121 JType elem_jty);
122
123 void Expand_ArrayPut(llvm::Value* new_value,
124 llvm::Value* array_addr,
125 llvm::Value* index_value,
126 JType elem_jty);
127
128 void Expand_FilledNewArray(llvm::CallInst& call_inst);
129
130 llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
131 llvm::Value* is_volatile_value,
132 llvm::Value* object_addr,
133 JType field_jty);
134
135 void Expand_IPutFast(llvm::Value* field_offset_value,
136 llvm::Value* is_volatile_value,
137 llvm::Value* object_addr,
138 llvm::Value* new_value,
139 JType field_jty);
140
141 llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
142 llvm::Value* field_offset_value,
143 llvm::Value* is_volatile_value,
144 JType field_jty);
145
146 void Expand_SPutFast(llvm::Value* static_storage_addr,
147 llvm::Value* field_offset_value,
148 llvm::Value* is_volatile_value,
149 llvm::Value* new_value,
150 JType field_jty);
151
152 llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
153
154 llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
155
156 llvm::Value*
157 Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
158
159 llvm::Value*
160 Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
161 llvm::Value* this_addr);
162
163 llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
164
165 llvm::Value* Expand_DivRem(llvm::Value* dividend, llvm::Value* divisor,
166 bool is_div, JType op_jty);
167
168 void Expand_AllocaShadowFrame(llvm::Value* num_entry_value);
169
170 void Expand_SetShadowFrameEntry(llvm::Value* obj, llvm::Value* entry_idx);
171
172 void Expand_PopShadowFrame();
173
174 void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
175
176 public:
177 static char ID;
178
179 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb)
180 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
181 context_(irb.getContext()), rtb_(irb.Runtime())
182 { }
183
184 bool runOnFunction(llvm::Function& func);
185
186 private:
187 bool InsertStackOverflowCheck(llvm::Function& func);
188
189 llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
190 llvm::CallInst& call_inst);
191
192};
193
194char GBCExpanderPass::ID = 0;
195
196bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
197 bool changed;
198
199 changed = InsertStackOverflowCheck(func);
200
201 std::list<std::pair<llvm::CallInst*,
202 IntrinsicHelper::IntrinsicId> > work_list;
203
204 for (llvm::inst_iterator inst_iter = llvm::inst_begin(func),
205 inst_end = llvm::inst_end(func); inst_iter != inst_end; inst_iter++) {
206 // Only CallInst with its called function is dexlang intrinsic need to
207 // process
208 llvm::Instruction* inst = &*inst_iter;
209 if (llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst)) {
210 const llvm::Function* callee = call_inst->getCalledFunction();
211
212 if (callee != NULL) {
213 IntrinsicHelper::IntrinsicId intr_id =
214 intrinsic_helper_.GetIntrinsicId(callee);
215
216 if (intr_id != IntrinsicHelper::UnknownId) {
217 work_list.push_back(std::make_pair(call_inst, intr_id));
218 }
219 }
220 }
221 }
222
223 changed |= !work_list.empty();
224
225 shadow_frame_ = NULL;
226 old_shadow_frame_ = NULL;
227 shadow_frame_size_ = 0;
228
229 // Remove the instruction containing in the work_list
230 while (!work_list.empty()) {
231 llvm::CallInst* intr_inst = work_list.front().first;
232 IntrinsicHelper::IntrinsicId intr_id = work_list.front().second;
233
234 // Remove the instruction from work list
235 work_list.pop_front();
236
237 // Move the IRBuilder insert pointer
238 irb_.SetInsertPoint(intr_inst);
239
240 // Process the expansion
241 llvm::Value* new_value = ExpandIntrinsic(intr_id, *intr_inst);
242
243 // Use the new value from the expansion
244 if (new_value != NULL) {
245 intr_inst->replaceAllUsesWith(new_value);
246 }
247
248 // Remove the intrinsic instruction
249 intr_inst->eraseFromParent();
250 }
251
252 VERIFY_LLVM_FUNCTION(func);
253
254 return changed;
255}
256
257llvm::BasicBlock*
258GBCExpanderPass::SplitAndInsertBasicBlocksAfter(llvm::BasicBlock::iterator inst,
259 llvm::BasicBlock* begin_bb,
260 llvm::BasicBlock* end_bb) {
261 llvm::BasicBlock* original = inst->getParent();
262 llvm::Function* parent = original->getParent();
263
264 // 1. Create a new basic block A after ORIGINAL
265 llvm::BasicBlock *insert_before =
266 llvm::next(llvm::Function::iterator(original)).getNodePtrUnchecked();
267 llvm::BasicBlock* a =
268 llvm::BasicBlock::Create(context_, "", parent, insert_before);
269
270 // 2. Move all instructions in ORIGINAL after INST (included) to A
271 a->getInstList().splice(a->end(), original->getInstList(),
272 inst, original->end());
273
274 // 3. Add an unconditional branch in ORIGINAL to begin_bb
275 llvm::BranchInst::Create(begin_bb, original);
276
277 // 4. Add an unconditional branch in END_BB to A
278 llvm::BranchInst::Create(a, end_bb);
279
280 // 5. Update the PHI nodes in the successors of A. Update the PHI node entry
281 // with incoming basic block from ORIGINAL to A
282 for (llvm::succ_iterator succ_iter = llvm::succ_begin(a),
283 succ_end = llvm::succ_end(a); succ_iter != succ_end; succ_iter++) {
284 llvm::BasicBlock* succ = *succ_iter;
285 llvm::PHINode* phi;
286 for (llvm::BasicBlock::iterator inst_iter = succ->begin();
287 (phi = llvm::dyn_cast<llvm::PHINode>(inst_iter)); ++inst_iter) {
288 int idx;
289 while ((idx = phi->getBasicBlockIndex(original)) != -1) {
290 phi->setIncomingBlock(static_cast<unsigned>(idx), a);
291 }
292 }
293 }
294
295 return a;
296}
297
298llvm::Value* GBCExpanderPass::ExpandToRuntime(runtime_support::RuntimeId rt,
299 llvm::CallInst& inst) {
300 // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
301 // the arguments passed to the GBC intrinsic are as the same as IBC runtime
302 // function, therefore only called function is needed to change.
303 unsigned num_args = inst.getNumArgOperands();
304
305 if (num_args <= 0) {
306 return irb_.CreateCall(irb_.GetRuntime(rt));
307 } else {
308 std::vector<llvm::Value*> args;
309 for (unsigned i = 0; i < num_args; i++) {
310 args.push_back(inst.getArgOperand(i));
311 }
312
313 return irb_.CreateCall(irb_.GetRuntime(rt), args);
314 }
315}
316
317bool
318GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
319 llvm::Function* func = first_non_alloca->getParent()->getParent();
320 llvm::Module* module = func->getParent();
321
322 llvm::BasicBlock* block_entry =
323 llvm::BasicBlock::Create(context_, "stack_overflow_entry", func);
324
325 irb_.SetInsertPoint(block_entry);
326
327 // Call llvm intrinsic function to get frame address.
328 llvm::Function* frameaddress =
329 llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
330
331 // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
332 llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
333
334 // Cast i8* to int
335 frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
336
337 // Get thread.stack_end_
338 llvm::Value* stack_end =
339 irb_.Runtime().EmitLoadFromThreadOffset(Thread::StackEndOffset().Int32Value(),
340 irb_.getPtrEquivIntTy(),
341 kTBAARuntimeInfo);
342
343 // Check the frame address < thread.stack_end_ ?
344 llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
345
346 llvm::BasicBlock* block_exception =
347 llvm::BasicBlock::Create(context_, "stack_overflow", func);
348
349 llvm::BasicBlock* block_continue =
350 llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
351
352 irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
353
354 // If stack overflow, throw exception.
355 irb_.SetInsertPoint(block_exception);
356 irb_.CreateCall(irb_.GetRuntime(runtime_support::ThrowStackOverflowException));
357
358 // Unwind.
359 llvm::Type* ret_type = func->getReturnType();
360 if (ret_type->isVoidTy()) {
361 irb_.CreateRetVoid();
362 } else {
363 // The return value is ignored when there's an exception. MethodCompiler
364 // returns zero value under the the corresponding return type in this case.
365 // GBCExpander returns LLVM undef value here for brevity
366 irb_.CreateRet(llvm::UndefValue::get(ret_type));
367 }
368
369 irb_.SetInsertPoint(block_continue);
370
371 SplitAndInsertBasicBlocksAfter(*first_non_alloca, block_entry, block_continue);
372
373 return true;
374}
375
376llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(MemberOffset offset) {
377 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
378
379 return irb_.LoadFromObjectOffset(method_object_addr,
380 offset.Int32Value(),
381 irb_.getJObjectTy(),
382 kTBAAConstJObject);
383}
384
385llvm::Value*
386GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
387 llvm::Value* static_storage_dex_cache_addr =
388 EmitLoadDexCacheAddr(Method::DexCacheInitializedStaticStorageOffset());
389
390 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
391
392 return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
393}
394
395llvm::Value*
396GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
397 llvm::Value* resolved_type_dex_cache_addr =
398 EmitLoadDexCacheAddr(Method::DexCacheResolvedTypesOffset());
399
400 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
401
402 return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
403}
404
405llvm::Value* GBCExpanderPass::
406EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
407 llvm::Value* resolved_method_dex_cache_addr =
408 EmitLoadDexCacheAddr(Method::DexCacheResolvedMethodsOffset());
409
410 llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
411
412 return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
413}
414
415llvm::Value* GBCExpanderPass::
416EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
417 llvm::Value* string_dex_cache_addr =
418 EmitLoadDexCacheAddr(Method::DexCacheStringsOffset());
419
420 llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
421
422 return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
423}
424
425llvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
426 llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
427 return parent_func->arg_begin();
428}
429
430llvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
431 // Load array length
432 return irb_.LoadFromObjectOffset(array,
433 Array::LengthOffset().Int32Value(),
434 irb_.getJIntTy(),
435 kTBAAConstJObject);
436
437}
438
439llvm::Value*
440GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
441 llvm::Value* callee_method_object_field_addr =
442 EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
443
444 return irb_.CreateLoad(callee_method_object_field_addr, kTBAAJRuntime);
445}
446
447llvm::Value* GBCExpanderPass::
448EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
449 // Load class object of *this* pointer
450 llvm::Value* class_object_addr =
451 irb_.LoadFromObjectOffset(this_addr,
452 Object::ClassOffset().Int32Value(),
453 irb_.getJObjectTy(),
454 kTBAAConstJObject);
455
456 // Load vtable address
457 llvm::Value* vtable_addr =
458 irb_.LoadFromObjectOffset(class_object_addr,
459 Class::VTableOffset().Int32Value(),
460 irb_.getJObjectTy(),
461 kTBAAConstJObject);
462
463 // Load callee method object
464 llvm::Value* vtable_idx_value =
465 irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
466
467 llvm::Value* method_field_addr =
468 EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
469
470 return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
471}
472
473// Emit Array GetElementPtr
474llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
475 llvm::Value* index_value,
476 JType elem_jty) {
477
478 int data_offset;
479 if (elem_jty == kLong || elem_jty == kDouble ||
480 (elem_jty == kObject && sizeof(uint64_t) == sizeof(Object*))) {
481 data_offset = Array::DataOffset(sizeof(int64_t)).Int32Value();
482 } else {
483 data_offset = Array::DataOffset(sizeof(int32_t)).Int32Value();
484 }
485
486 llvm::Constant* data_offset_value =
487 irb_.getPtrEquivInt(data_offset);
488
489 llvm::Type* elem_type = irb_.getJType(elem_jty, kArray);
490
491 llvm::Value* array_data_addr =
492 irb_.CreatePtrDisp(array_addr, data_offset_value,
493 elem_type->getPointerTo());
494
495 return irb_.CreateGEP(array_data_addr, index_value);
496}
497
498void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
499 llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
500 llvm::BasicBlock* suspend_test_begin_bb =
501 llvm::BasicBlock::Create(context_, "suspend_test", parent_func);
502
503 irb_.SetInsertPoint(suspend_test_begin_bb);
504 irb_.Runtime().EmitTestSuspend();
505
506 llvm::BasicBlock* suspend_test_end_bb = irb_.GetInsertBlock();
507
508 SplitAndInsertBasicBlocksAfter(call_inst, suspend_test_begin_bb,
509 suspend_test_end_bb);
510 return;
511}
512
513llvm::Value* GBCExpanderPass::Expand_GetException() {
514 // Get thread-local exception field address
515 llvm::Value* exception_object_addr =
516 irb_.Runtime().EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
517 irb_.getJObjectTy(),
518 kTBAAJRuntime);
519
520 // Set thread-local exception field address to NULL
521 irb_.Runtime().EmitStoreToThreadOffset(Thread::ExceptionOffset().Int32Value(),
522 irb_.getJNull(),
523 kTBAAJRuntime);
524
525 return exception_object_addr;
526}
527
528llvm::Value*
529GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
530 uint32_t string_idx =
531 llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
532
533 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
534
535 return irb_.CreateLoad(string_field_addr, kTBAAJRuntime);
536}
537
538llvm::Value*
539GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
540 uint32_t type_idx =
541 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
542
543 llvm::Value* type_field_addr =
544 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
545
546 return irb_.CreateLoad(type_field_addr, kTBAAJRuntime);
547}
548
549void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
550 llvm::BasicBlock::iterator lock_obj_inst = irb_.GetInsertPoint();
551 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
552
553 llvm::BasicBlock* lock_obj_begin_bb =
554 llvm::BasicBlock::Create(context_, "", parent);
555
556 irb_.SetInsertPoint(lock_obj_begin_bb);
557 rtb_.EmitLockObject(obj);
558
559 llvm::BasicBlock* lock_obj_end_bb = irb_.GetInsertBlock();
560
561 SplitAndInsertBasicBlocksAfter(lock_obj_inst, lock_obj_begin_bb,
562 lock_obj_end_bb);
563
564 return;
565}
566
567void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
568 llvm::BasicBlock::iterator unlock_obj_inst = irb_.GetInsertPoint();
569 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
570
571 llvm::BasicBlock* unlock_obj_begin_bb =
572 llvm::BasicBlock::Create(context_, "", parent);
573
574 irb_.SetInsertPoint(unlock_obj_begin_bb);
575 rtb_.EmitUnlockObject(obj);
576
577 llvm::BasicBlock* unlock_obj_end_bb = irb_.GetInsertBlock();
578
579 SplitAndInsertBasicBlocksAfter(unlock_obj_inst, unlock_obj_begin_bb,
580 unlock_obj_end_bb);
581
582 return;
583}
584
585llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
586 llvm::Value* index_value,
587 JType elem_jty) {
588 llvm::Value* array_elem_addr =
589 EmitArrayGEP(array_addr, index_value, elem_jty);
590
591 return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
592}
593
594void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
595 llvm::Value* array_addr,
596 llvm::Value* index_value,
597 JType elem_jty) {
598 llvm::Value* array_elem_addr =
599 EmitArrayGEP(array_addr, index_value, elem_jty);
600
601 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
602
603 return;
604}
605
606void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
607 // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
608 llvm::Value* array = call_inst.getArgOperand(0);
609
610 uint32_t element_jty =
611 llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
612
613 DCHECK(call_inst.getNumArgOperands() > 2);
614 unsigned num_elements = (call_inst.getNumArgOperands() - 2);
615
616 bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
617
618 uint32_t alignment;
619 llvm::Constant* elem_size;
620 llvm::PointerType* field_type;
621
622 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
623 // as the element, thus we are only checking 2 cases: primitive int and
624 // non-primitive type.
625 if (is_elem_int_ty) {
626 alignment = sizeof(int32_t);
627 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
628 field_type = irb_.getJIntTy()->getPointerTo();
629 } else {
630 alignment = irb_.getSizeOfPtrEquivInt();
631 elem_size = irb_.getSizeOfPtrEquivIntValue();
632 field_type = irb_.getJObjectTy()->getPointerTo();
633 }
634
635 llvm::Value* data_field_offset =
636 irb_.getPtrEquivInt(Array::DataOffset(alignment).Int32Value());
637
638 llvm::Value* data_field_addr =
639 irb_.CreatePtrDisp(array, data_field_offset, field_type);
640
641 for (unsigned i = 0; i < num_elements; ++i) {
642 // Values to fill the array begin at the 3rd argument
643 llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
644
645 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
646
647 data_field_addr =
648 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
649 }
650
651 return;
652}
653
654llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
655 llvm::Value* /*is_volatile_value*/,
656 llvm::Value* object_addr,
657 JType field_jty) {
658 int field_offset =
659 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
660
661 DCHECK_GE(field_offset, 0);
662
663 llvm::PointerType* field_type =
664 irb_.getJType(field_jty, kField)->getPointerTo();
665
666 field_offset_value = irb_.getPtrEquivInt(field_offset);
667
668 llvm::Value* field_addr =
669 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
670
671 // TODO: Check is_volatile. We need to generate atomic load instruction
672 // when is_volatile is true.
673 return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
674}
675
676void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
677 llvm::Value* /* is_volatile_value */,
678 llvm::Value* object_addr,
679 llvm::Value* new_value,
680 JType field_jty) {
681 int field_offset =
682 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
683
684 DCHECK_GE(field_offset, 0);
685
686 llvm::PointerType* field_type =
687 irb_.getJType(field_jty, kField)->getPointerTo();
688
689 field_offset_value = irb_.getPtrEquivInt(field_offset);
690
691 llvm::Value* field_addr =
692 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
693
694 // TODO: Check is_volatile. We need to generate atomic store instruction
695 // when is_volatile is true.
696 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
697
698 return;
699}
700
701llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
702 llvm::Value* field_offset_value,
703 llvm::Value* /*is_volatile_value*/,
704 JType field_jty) {
705 int field_offset =
706 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
707
708 DCHECK_GE(field_offset, 0);
709
710 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
711
712 llvm::Value* static_field_addr =
713 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
714 irb_.getJType(field_jty, kField)->getPointerTo());
715
716 // TODO: Check is_volatile. We need to generate atomic store instruction
717 // when is_volatile is true.
718 return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
719}
720
721void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
722 llvm::Value* field_offset_value,
723 llvm::Value* /* is_volatile_value */,
724 llvm::Value* new_value,
725 JType field_jty) {
726 int field_offset =
727 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
728
729 DCHECK_GE(field_offset, 0);
730
731 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
732
733 llvm::Value* static_field_addr =
734 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
735 irb_.getJType(field_jty, kField)->getPointerTo());
736
737 // TODO: Check is_volatile. We need to generate atomic store instruction
738 // when is_volatile is true.
739 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
740
741 return;
742}
743
744llvm::Value*
745GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
746 return irb_.LoadFromObjectOffset(method_object_addr,
747 Method::DeclaringClassOffset().Int32Value(),
748 irb_.getJObjectTy(),
749 kTBAAConstJObject);
750}
751
752llvm::Value*
753GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
754 uint32_t type_idx =
755 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
756
757 llvm::Value* storage_field_addr =
758 EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
759
760 return irb_.CreateLoad(storage_field_addr, kTBAAJRuntime);
761}
762
763llvm::Value*
764GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
765 uint32_t callee_method_idx =
766 llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
767
768 return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
769}
770
771llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
772 llvm::Value* vtable_idx_value,
773 llvm::Value* this_addr) {
774 int vtable_idx =
775 llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
776
777 return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
778}
779
780llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
781 // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
782 llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
783 unsigned num_args = call_inst.getNumArgOperands();
784 llvm::Type* ret_type = call_inst.getType();
785
786 // Determine the function type of the callee method
787 std::vector<llvm::Type*> args_type;
788 std::vector<llvm::Value*> args;
789 for (unsigned i = 0; i < num_args; i++) {
790 args.push_back(call_inst.getArgOperand(i));
791 args_type.push_back(args[i]->getType());
792 }
793
794 llvm::FunctionType* callee_method_type =
795 llvm::FunctionType::get(ret_type, args_type, false);
796
797 llvm::Value* code_addr =
798 irb_.LoadFromObjectOffset(callee_method_object_addr,
799 Method::GetCodeOffset().Int32Value(),
800 callee_method_type->getPointerTo(),
801 kTBAAJRuntime);
802
803 // Invoke callee
804 llvm::Value* retval = irb_.CreateCall(code_addr, args);
805
806 return retval;
807}
808
809llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::Value* dividend,
810 llvm::Value* divisor,
811 bool is_div, JType op_jty) {
812 // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
813
814 // Check the special case: MININT / -1 = MININT
815 // That case will cause overflow, which is undefined behavior in llvm.
816 // So we check the divisor is -1 or not, if the divisor is -1, we do
817 // the special path to avoid undefined behavior.
818 llvm::Type* op_type = irb_.getJType(op_jty, kAccurate);
819 llvm::Value* zero = irb_.getJZero(op_jty);
820 llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
821
822 llvm::BasicBlock::iterator div_rem_inst = irb_.GetInsertPoint();
823 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
824
825 llvm::BasicBlock* begin_div_rem =
826 llvm::BasicBlock::Create(context_, "", parent);
827 llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
828 llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
829 llvm::BasicBlock* neg_one_cont =
830 llvm::BasicBlock::Create(context_, "", parent);
831
832 irb_.SetInsertPoint(begin_div_rem);
833 llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
834 irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
835
836 // If divisor == -1
837 irb_.SetInsertPoint(eq_neg_one);
838 llvm::Value* eq_result;
839 if (is_div) {
840 // We can just change from "dividend div -1" to "neg dividend". The sub
841 // don't care the sign/unsigned because of two's complement representation.
842 // And the behavior is what we want:
843 // -(2^n) (2^n)-1
844 // MININT < k <= MAXINT -> mul k -1 = -k
845 // MININT == k -> mul k -1 = k
846 //
847 // LLVM use sub to represent 'neg'
848 eq_result = irb_.CreateSub(zero, dividend);
849 } else {
850 // Everything modulo -1 will be 0.
851 eq_result = zero;
852 }
853 irb_.CreateBr(neg_one_cont);
854
855 // If divisor != -1, just do the division.
856 irb_.SetInsertPoint(ne_neg_one);
857 llvm::Value* ne_result;
858 if (is_div) {
859 ne_result = irb_.CreateSDiv(dividend, divisor);
860 } else {
861 ne_result = irb_.CreateSRem(dividend, divisor);
862 }
863 irb_.CreateBr(neg_one_cont);
864
865 irb_.SetInsertPoint(neg_one_cont);
866 llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
867 result->addIncoming(eq_result, eq_neg_one);
868 result->addIncoming(ne_result, ne_neg_one);
869
870 SplitAndInsertBasicBlocksAfter(div_rem_inst, begin_div_rem, neg_one_cont);
871
872 return result;
873}
874
875void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_entry_value) {
876 // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
877 // MethodCompiler::EmitPushShadowFrame
878 shadow_frame_size_ =
879 llvm::cast<llvm::ConstantInt>(num_entry_value)->getZExtValue();
880
881 llvm::StructType* shadow_frame_type =
882 irb_.getShadowFrameTy(shadow_frame_size_);
883
884 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
885
886 // Alloca a pointer to old shadow frame
887 old_shadow_frame_ =
888 irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
889
890 // Zero-initialization of the shadow frame table
891 llvm::Value* shadow_frame_table =
892 irb_.CreateConstGEP2_32(shadow_frame_, 0, 1);
893 llvm::Type* table_type = shadow_frame_type->getElementType(1);
894
895 llvm::ConstantAggregateZero* zero_initializer =
896 llvm::ConstantAggregateZero::get(table_type);
897
898 irb_.CreateStore(zero_initializer, shadow_frame_table, kTBAAShadowFrame);
899
900 // Push the shadow frame
901 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
902
903 // Push the shadow frame
904 llvm::Value* shadow_frame_upcast =
905 irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
906
907 llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
908 method_object_addr,
909 shadow_frame_size_);
910
911 irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
912
913 return;
914}
915
916void GBCExpanderPass::Expand_SetShadowFrameEntry(llvm::Value* obj,
917 llvm::Value* entry_idx) {
918 DCHECK(shadow_frame_ != NULL);
919
920 llvm::Value* gep_index[] = {
921 irb_.getInt32(0), // No pointer displacement
922 irb_.getInt32(1), // SIRT
923 entry_idx // Pointer field
924 };
925
926 llvm::Value* entry_addr = irb_.CreateGEP(shadow_frame_, gep_index);
927 irb_.CreateStore(obj, entry_addr, kTBAAShadowFrame);
928 return;
929}
930
931void GBCExpanderPass::Expand_PopShadowFrame() {
932 rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
933 return;
934}
935
936void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
937 irb_.StoreToObjectOffset(shadow_frame_,
938 ShadowFrame::DexPCOffset(),
939 dex_pc_value,
940 kTBAAShadowFrame);
941 return;
942}
943
944bool GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
945 // DexLang generates all alloca instruction in the first basic block of the
946 // FUNC and also there's no any alloca instructions after the first non-alloca
947 // instruction
948
949 llvm::BasicBlock::iterator first_non_alloca = func.front().begin();
950 while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
951 ++first_non_alloca;
952 }
953
954 // Insert stack overflow check codes before first_non_alloca (i.e., after all
955 // alloca instructions)
956 return EmitStackOverflowCheck(&*first_non_alloca);
957}
958
959llvm::Value*
960GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
961 llvm::CallInst& call_inst) {
962 switch (intr_id) {
963 //==- Thread -----------------------------------------------------------==//
964 case IntrinsicHelper::GetCurrentThread: {
965 return ExpandToRuntime(runtime_support::GetCurrentThread, call_inst);
966 }
967 case IntrinsicHelper::TestSuspend: {
968 Expand_TestSuspend(call_inst);
969 return NULL;
970 }
971 case IntrinsicHelper::MarkGCCard: {
972 return ExpandToRuntime(runtime_support::MarkGCCard, call_inst);
973 }
974 //==- Exception --------------------------------------------------------==//
975 case IntrinsicHelper::ThrowException: {
976 return ExpandToRuntime(runtime_support::ThrowException, call_inst);
977 }
978 case IntrinsicHelper::GetException: {
979 return Expand_GetException();
980 }
981 case IntrinsicHelper::IsExceptionPending: {
982 return irb_.Runtime().EmitIsExceptionPending();
983 }
984 case IntrinsicHelper::FindCatchBlock: {
985 return ExpandToRuntime(runtime_support::FindCatchBlock, call_inst);
986 }
987 case IntrinsicHelper::ThrowDivZeroException: {
988 return ExpandToRuntime(runtime_support::ThrowDivZeroException, call_inst);
989 }
990 case IntrinsicHelper::ThrowNullPointerException: {
991 return ExpandToRuntime(runtime_support::ThrowNullPointerException, call_inst);
992 }
993 case IntrinsicHelper::ThrowIndexOutOfBounds: {
994 return ExpandToRuntime(runtime_support::ThrowIndexOutOfBounds, call_inst);
995 }
996 //==- ConstString ------------------------------------------------------==//
997 case IntrinsicHelper::LoadStringFromDexCache: {
998 return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
999 }
1000 case IntrinsicHelper::ResolveString: {
1001 return ExpandToRuntime(runtime_support::ResolveString, call_inst);
1002 }
1003 //==- ConstClass -------------------------------------------------------==//
1004 case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
1005 return ExpandToRuntime(runtime_support::InitializeTypeAndVerifyAccess, call_inst);
1006 }
1007 case IntrinsicHelper::LoadTypeFromDexCache: {
1008 return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
1009 }
1010 case IntrinsicHelper::InitializeType: {
1011 return ExpandToRuntime(runtime_support::InitializeType, call_inst);
1012 }
1013 //==- Lock -------------------------------------------------------------==//
1014 case IntrinsicHelper::LockObject: {
1015 Expand_LockObject(call_inst.getArgOperand(0));
1016 return NULL;
1017 }
1018 case IntrinsicHelper::UnlockObject: {
1019 Expand_UnlockObject(call_inst.getArgOperand(0));
1020 return NULL;
1021 }
1022 //==- Cast -------------------------------------------------------------==//
1023 case IntrinsicHelper::CheckCast: {
1024 return ExpandToRuntime(runtime_support::CheckCast, call_inst);
1025 }
1026 case IntrinsicHelper::IsAssignable: {
1027 return ExpandToRuntime(runtime_support::IsAssignable, call_inst);
1028 }
1029 //==- Alloc ------------------------------------------------------------==//
1030 case IntrinsicHelper::AllocObject: {
1031 return ExpandToRuntime(runtime_support::AllocObject, call_inst);
1032 }
1033 case IntrinsicHelper::AllocObjectWithAccessCheck: {
1034 return ExpandToRuntime(runtime_support::AllocObjectWithAccessCheck, call_inst);
1035 }
1036 //==- Array ------------------------------------------------------------==//
1037 case IntrinsicHelper::ArrayLength: {
1038 return EmitLoadArrayLength(call_inst.getArgOperand(0));
1039 }
1040 case IntrinsicHelper::AllocArray: {
1041 return ExpandToRuntime(runtime_support::AllocArray, call_inst);
1042 }
1043 case IntrinsicHelper::AllocArrayWithAccessCheck: {
1044 return ExpandToRuntime(runtime_support::AllocArrayWithAccessCheck,
1045 call_inst);
1046 }
1047 case IntrinsicHelper::CheckAndAllocArray: {
1048 return ExpandToRuntime(runtime_support::CheckAndAllocArray, call_inst);
1049 }
1050 case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
1051 return ExpandToRuntime(runtime_support::CheckAndAllocArrayWithAccessCheck,
1052 call_inst);
1053 }
1054 case IntrinsicHelper::ArrayGet: {
1055 return Expand_ArrayGet(call_inst.getArgOperand(0),
1056 call_inst.getArgOperand(1),
1057 kInt);
1058 }
1059 case IntrinsicHelper::ArrayGetWide: {
1060 return Expand_ArrayGet(call_inst.getArgOperand(0),
1061 call_inst.getArgOperand(1),
1062 kLong);
1063 }
1064 case IntrinsicHelper::ArrayGetObject: {
1065 return Expand_ArrayGet(call_inst.getArgOperand(0),
1066 call_inst.getArgOperand(1),
1067 kObject);
1068 }
1069 case IntrinsicHelper::ArrayGetBoolean: {
1070 return Expand_ArrayGet(call_inst.getArgOperand(0),
1071 call_inst.getArgOperand(1),
1072 kBoolean);
1073 }
1074 case IntrinsicHelper::ArrayGetByte: {
1075 return Expand_ArrayGet(call_inst.getArgOperand(0),
1076 call_inst.getArgOperand(1),
1077 kByte);
1078 }
1079 case IntrinsicHelper::ArrayGetChar: {
1080 return Expand_ArrayGet(call_inst.getArgOperand(0),
1081 call_inst.getArgOperand(1),
1082 kChar);
1083 }
1084 case IntrinsicHelper::ArrayGetShort: {
1085 return Expand_ArrayGet(call_inst.getArgOperand(0),
1086 call_inst.getArgOperand(1),
1087 kShort);
1088 }
1089 case IntrinsicHelper::ArrayPut: {
1090 Expand_ArrayPut(call_inst.getArgOperand(0),
1091 call_inst.getArgOperand(1),
1092 call_inst.getArgOperand(2),
1093 kInt);
1094 return NULL;
1095 }
1096 case IntrinsicHelper::ArrayPutWide: {
1097 Expand_ArrayPut(call_inst.getArgOperand(0),
1098 call_inst.getArgOperand(1),
1099 call_inst.getArgOperand(2),
1100 kLong);
1101 return NULL;
1102 }
1103 case IntrinsicHelper::ArrayPutObject: {
1104 Expand_ArrayPut(call_inst.getArgOperand(0),
1105 call_inst.getArgOperand(1),
1106 call_inst.getArgOperand(2),
1107 kObject);
1108 return NULL;
1109 }
1110 case IntrinsicHelper::ArrayPutBoolean: {
1111 Expand_ArrayPut(call_inst.getArgOperand(0),
1112 call_inst.getArgOperand(1),
1113 call_inst.getArgOperand(2),
1114 kBoolean);
1115 return NULL;
1116 }
1117 case IntrinsicHelper::ArrayPutByte: {
1118 Expand_ArrayPut(call_inst.getArgOperand(0),
1119 call_inst.getArgOperand(1),
1120 call_inst.getArgOperand(2),
1121 kByte);
1122 return NULL;
1123 }
1124 case IntrinsicHelper::ArrayPutChar: {
1125 Expand_ArrayPut(call_inst.getArgOperand(0),
1126 call_inst.getArgOperand(1),
1127 call_inst.getArgOperand(2),
1128 kChar);
1129 return NULL;
1130 }
1131 case IntrinsicHelper::ArrayPutShort: {
1132 Expand_ArrayPut(call_inst.getArgOperand(0),
1133 call_inst.getArgOperand(1),
1134 call_inst.getArgOperand(2),
1135 kShort);
1136 return NULL;
1137 }
1138 case IntrinsicHelper::CheckPutArrayElement: {
1139 return ExpandToRuntime(runtime_support::CheckPutArrayElement, call_inst);
1140 }
1141 case IntrinsicHelper::FilledNewArray: {
1142 Expand_FilledNewArray(call_inst);
1143 return NULL;
1144 }
1145 case IntrinsicHelper::FillArrayData: {
1146 return ExpandToRuntime(runtime_support::FillArrayData, call_inst);
1147 }
1148 //==- Instance Field ---------------------------------------------------==//
1149 case IntrinsicHelper::InstanceFieldGet:
1150 case IntrinsicHelper::InstanceFieldGetBoolean:
1151 case IntrinsicHelper::InstanceFieldGetByte:
1152 case IntrinsicHelper::InstanceFieldGetChar:
1153 case IntrinsicHelper::InstanceFieldGetShort: {
1154 return ExpandToRuntime(runtime_support::Get32Instance, call_inst);
1155 }
1156 case IntrinsicHelper::InstanceFieldGetWide: {
1157 return ExpandToRuntime(runtime_support::Get64Instance, call_inst);
1158 }
1159 case IntrinsicHelper::InstanceFieldGetObject: {
1160 return ExpandToRuntime(runtime_support::GetObjectInstance, call_inst);
1161 }
1162 case IntrinsicHelper::InstanceFieldGetFast: {
1163 return Expand_IGetFast(call_inst.getArgOperand(0),
1164 call_inst.getArgOperand(1),
1165 call_inst.getArgOperand(2),
1166 kInt);
1167 }
1168 case IntrinsicHelper::InstanceFieldGetWideFast: {
1169 return Expand_IGetFast(call_inst.getArgOperand(0),
1170 call_inst.getArgOperand(1),
1171 call_inst.getArgOperand(2),
1172 kLong);
1173 }
1174 case IntrinsicHelper::InstanceFieldGetObjectFast: {
1175 return Expand_IGetFast(call_inst.getArgOperand(0),
1176 call_inst.getArgOperand(1),
1177 call_inst.getArgOperand(2),
1178 kObject);
1179 }
1180 case IntrinsicHelper::InstanceFieldGetBooleanFast: {
1181 return Expand_IGetFast(call_inst.getArgOperand(0),
1182 call_inst.getArgOperand(1),
1183 call_inst.getArgOperand(2),
1184 kBoolean);
1185 }
1186 case IntrinsicHelper::InstanceFieldGetByteFast: {
1187 return Expand_IGetFast(call_inst.getArgOperand(0),
1188 call_inst.getArgOperand(1),
1189 call_inst.getArgOperand(2),
1190 kByte);
1191 }
1192 case IntrinsicHelper::InstanceFieldGetCharFast: {
1193 return Expand_IGetFast(call_inst.getArgOperand(0),
1194 call_inst.getArgOperand(1),
1195 call_inst.getArgOperand(2),
1196 kChar);
1197 }
1198 case IntrinsicHelper::InstanceFieldGetShortFast: {
1199 return Expand_IGetFast(call_inst.getArgOperand(0),
1200 call_inst.getArgOperand(1),
1201 call_inst.getArgOperand(2),
1202 kShort);
1203 }
1204 case IntrinsicHelper::InstanceFieldPut:
1205 case IntrinsicHelper::InstanceFieldPutBoolean:
1206 case IntrinsicHelper::InstanceFieldPutByte:
1207 case IntrinsicHelper::InstanceFieldPutChar:
1208 case IntrinsicHelper::InstanceFieldPutShort: {
1209 return ExpandToRuntime(runtime_support::Set32Instance, call_inst);
1210 }
1211 case IntrinsicHelper::InstanceFieldPutWide: {
1212 return ExpandToRuntime(runtime_support::Set64Instance, call_inst);
1213 }
1214 case IntrinsicHelper::InstanceFieldPutObject: {
1215 return ExpandToRuntime(runtime_support::SetObjectInstance, call_inst);
1216 }
1217 case IntrinsicHelper::InstanceFieldPutFast: {
1218 Expand_IPutFast(call_inst.getArgOperand(0),
1219 call_inst.getArgOperand(1),
1220 call_inst.getArgOperand(2),
1221 call_inst.getArgOperand(3),
1222 kInt);
1223 return NULL;
1224 }
1225 case IntrinsicHelper::InstanceFieldPutWideFast: {
1226 Expand_IPutFast(call_inst.getArgOperand(0),
1227 call_inst.getArgOperand(1),
1228 call_inst.getArgOperand(2),
1229 call_inst.getArgOperand(3),
1230 kLong);
1231 return NULL;
1232 }
1233 case IntrinsicHelper::InstanceFieldPutObjectFast: {
1234 Expand_IPutFast(call_inst.getArgOperand(0),
1235 call_inst.getArgOperand(1),
1236 call_inst.getArgOperand(2),
1237 call_inst.getArgOperand(3),
1238 kObject);
1239 return NULL;
1240 }
1241 case IntrinsicHelper::InstanceFieldPutBooleanFast: {
1242 Expand_IPutFast(call_inst.getArgOperand(0),
1243 call_inst.getArgOperand(1),
1244 call_inst.getArgOperand(2),
1245 call_inst.getArgOperand(3),
1246 kBoolean);
1247 return NULL;
1248 }
1249 case IntrinsicHelper::InstanceFieldPutByteFast: {
1250 Expand_IPutFast(call_inst.getArgOperand(0),
1251 call_inst.getArgOperand(1),
1252 call_inst.getArgOperand(2),
1253 call_inst.getArgOperand(3),
1254 kByte);
1255 return NULL;
1256 }
1257 case IntrinsicHelper::InstanceFieldPutCharFast: {
1258 Expand_IPutFast(call_inst.getArgOperand(0),
1259 call_inst.getArgOperand(1),
1260 call_inst.getArgOperand(2),
1261 call_inst.getArgOperand(3),
1262 kChar);
1263 return NULL;
1264 }
1265 case IntrinsicHelper::InstanceFieldPutShortFast: {
1266 Expand_IPutFast(call_inst.getArgOperand(0),
1267 call_inst.getArgOperand(1),
1268 call_inst.getArgOperand(2),
1269 call_inst.getArgOperand(3),
1270 kShort);
1271 return NULL;
1272 }
1273 //==- Static Field -----------------------------------------------------==//
1274 case IntrinsicHelper::StaticFieldGet:
1275 case IntrinsicHelper::StaticFieldGetBoolean:
1276 case IntrinsicHelper::StaticFieldGetByte:
1277 case IntrinsicHelper::StaticFieldGetChar:
1278 case IntrinsicHelper::StaticFieldGetShort: {
1279 return ExpandToRuntime(runtime_support::Get32Static, call_inst);
1280 }
1281 case IntrinsicHelper::StaticFieldGetWide: {
1282 return ExpandToRuntime(runtime_support::Get64Static, call_inst);
1283 }
1284 case IntrinsicHelper::StaticFieldGetObject: {
1285 return ExpandToRuntime(runtime_support::GetObjectStatic, call_inst);
1286 }
1287 case IntrinsicHelper::StaticFieldGetFast: {
1288 return Expand_SGetFast(call_inst.getArgOperand(0),
1289 call_inst.getArgOperand(1),
1290 call_inst.getArgOperand(2),
1291 kInt);
1292 }
1293 case IntrinsicHelper::StaticFieldGetWideFast: {
1294 return Expand_SGetFast(call_inst.getArgOperand(0),
1295 call_inst.getArgOperand(1),
1296 call_inst.getArgOperand(2),
1297 kLong);
1298 }
1299 case IntrinsicHelper::StaticFieldGetObjectFast: {
1300 return Expand_SGetFast(call_inst.getArgOperand(0),
1301 call_inst.getArgOperand(1),
1302 call_inst.getArgOperand(2),
1303 kObject);
1304 }
1305 case IntrinsicHelper::StaticFieldGetBooleanFast: {
1306 return Expand_SGetFast(call_inst.getArgOperand(0),
1307 call_inst.getArgOperand(1),
1308 call_inst.getArgOperand(2),
1309 kBoolean);
1310 }
1311 case IntrinsicHelper::StaticFieldGetByteFast: {
1312 return Expand_SGetFast(call_inst.getArgOperand(0),
1313 call_inst.getArgOperand(1),
1314 call_inst.getArgOperand(2),
1315 kByte);
1316 }
1317 case IntrinsicHelper::StaticFieldGetCharFast: {
1318 return Expand_SGetFast(call_inst.getArgOperand(0),
1319 call_inst.getArgOperand(1),
1320 call_inst.getArgOperand(2),
1321 kChar);
1322 }
1323 case IntrinsicHelper::StaticFieldGetShortFast: {
1324 return Expand_SGetFast(call_inst.getArgOperand(0),
1325 call_inst.getArgOperand(1),
1326 call_inst.getArgOperand(2),
1327 kShort);
1328 }
1329 case IntrinsicHelper::StaticFieldPut:
1330 case IntrinsicHelper::StaticFieldPutBoolean:
1331 case IntrinsicHelper::StaticFieldPutByte:
1332 case IntrinsicHelper::StaticFieldPutChar:
1333 case IntrinsicHelper::StaticFieldPutShort: {
1334 return ExpandToRuntime(runtime_support::Set32Static, call_inst);
1335 }
1336 case IntrinsicHelper::StaticFieldPutWide: {
1337 return ExpandToRuntime(runtime_support::Set64Static, call_inst);
1338 }
1339 case IntrinsicHelper::StaticFieldPutObject: {
1340 return ExpandToRuntime(runtime_support::SetObjectStatic, call_inst);
1341 }
1342 case IntrinsicHelper::StaticFieldPutFast: {
1343 Expand_SPutFast(call_inst.getArgOperand(0),
1344 call_inst.getArgOperand(1),
1345 call_inst.getArgOperand(2),
1346 call_inst.getArgOperand(3),
1347 kInt);
1348 return NULL;
1349 }
1350 case IntrinsicHelper::StaticFieldPutWideFast: {
1351 Expand_SPutFast(call_inst.getArgOperand(0),
1352 call_inst.getArgOperand(1),
1353 call_inst.getArgOperand(2),
1354 call_inst.getArgOperand(3),
1355 kLong);
1356 return NULL;
1357 }
1358 case IntrinsicHelper::StaticFieldPutObjectFast: {
1359 Expand_SPutFast(call_inst.getArgOperand(0),
1360 call_inst.getArgOperand(1),
1361 call_inst.getArgOperand(2),
1362 call_inst.getArgOperand(3),
1363 kObject);
1364 return NULL;
1365 }
1366 case IntrinsicHelper::StaticFieldPutBooleanFast: {
1367 Expand_SPutFast(call_inst.getArgOperand(0),
1368 call_inst.getArgOperand(1),
1369 call_inst.getArgOperand(2),
1370 call_inst.getArgOperand(3),
1371 kBoolean);
1372 return NULL;
1373 }
1374 case IntrinsicHelper::StaticFieldPutByteFast: {
1375 Expand_SPutFast(call_inst.getArgOperand(0),
1376 call_inst.getArgOperand(1),
1377 call_inst.getArgOperand(2),
1378 call_inst.getArgOperand(3),
1379 kByte);
1380 return NULL;
1381 }
1382 case IntrinsicHelper::StaticFieldPutCharFast: {
1383 Expand_SPutFast(call_inst.getArgOperand(0),
1384 call_inst.getArgOperand(1),
1385 call_inst.getArgOperand(2),
1386 call_inst.getArgOperand(3),
1387 kChar);
1388 return NULL;
1389 }
1390 case IntrinsicHelper::StaticFieldPutShortFast: {
1391 Expand_SPutFast(call_inst.getArgOperand(0),
1392 call_inst.getArgOperand(1),
1393 call_inst.getArgOperand(2),
1394 call_inst.getArgOperand(3),
1395 kShort);
1396 return NULL;
1397 }
1398 case IntrinsicHelper::LoadDeclaringClassSSB: {
1399 return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
1400 }
1401 case IntrinsicHelper::LoadClassSSBFromDexCache: {
1402 return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
1403 }
1404 case IntrinsicHelper::InitializeAndLoadClassSSB: {
1405 return ExpandToRuntime(runtime_support::InitializeStaticStorage, call_inst);
1406 }
1407 //==- Invoke -----------------------------------------------------------==//
1408 case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
1409 return ExpandToRuntime(runtime_support::FindStaticMethodWithAccessCheck, call_inst);
1410 }
1411 case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
1412 return ExpandToRuntime(runtime_support::FindDirectMethodWithAccessCheck, call_inst);
1413 }
1414 case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
1415 return ExpandToRuntime(runtime_support::FindVirtualMethodWithAccessCheck, call_inst);
1416 }
1417 case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
1418 return ExpandToRuntime(runtime_support::FindSuperMethodWithAccessCheck, call_inst);
1419 }
1420 case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
1421 return ExpandToRuntime(runtime_support::FindInterfaceMethodWithAccessCheck, call_inst);
1422 }
1423 case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
1424 return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
1425 }
1426 case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
1427 return Expand_GetVirtualCalleeMethodObjAddrFast(
1428 call_inst.getArgOperand(0), call_inst.getArgOperand(1));
1429 }
1430 case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
1431 return ExpandToRuntime(runtime_support::FindInterfaceMethod, call_inst);
1432 }
1433 case IntrinsicHelper::InvokeRetVoid:
1434 case IntrinsicHelper::InvokeRetBoolean:
1435 case IntrinsicHelper::InvokeRetByte:
1436 case IntrinsicHelper::InvokeRetChar:
1437 case IntrinsicHelper::InvokeRetShort:
1438 case IntrinsicHelper::InvokeRetInt:
1439 case IntrinsicHelper::InvokeRetLong:
1440 case IntrinsicHelper::InvokeRetFloat:
1441 case IntrinsicHelper::InvokeRetDouble:
1442 case IntrinsicHelper::InvokeRetObject: {
1443 return Expand_Invoke(call_inst);
1444 }
1445 //==- Math -------------------------------------------------------------==//
1446 case IntrinsicHelper::DivInt: {
1447 return Expand_DivRem(call_inst.getArgOperand(0),
1448 call_inst.getArgOperand(1),
1449 /* is_div */true, kInt);
1450 }
1451 case IntrinsicHelper::RemInt: {
1452 return Expand_DivRem(call_inst.getArgOperand(0),
1453 call_inst.getArgOperand(1),
1454 /* is_div */false, kInt);
1455 }
1456 case IntrinsicHelper::DivLong: {
1457 return Expand_DivRem(call_inst.getArgOperand(0),
1458 call_inst.getArgOperand(1),
1459 /* is_div */true, kLong);
1460 }
1461 case IntrinsicHelper::RemLong: {
1462 return Expand_DivRem(call_inst.getArgOperand(0),
1463 call_inst.getArgOperand(1),
1464 /* is_div */false, kLong);
1465 }
1466 case IntrinsicHelper::D2L: {
1467 return ExpandToRuntime(runtime_support::art_d2l, call_inst);
1468 }
1469 case IntrinsicHelper::D2I: {
1470 return ExpandToRuntime(runtime_support::art_d2i, call_inst);
1471 }
1472 case IntrinsicHelper::F2L: {
1473 return ExpandToRuntime(runtime_support::art_f2l, call_inst);
1474 }
1475 case IntrinsicHelper::F2I: {
1476 return ExpandToRuntime(runtime_support::art_f2i, call_inst);
1477 }
1478 //==- Shadow Frame -----------------------------------------------------==//
1479 case IntrinsicHelper::AllocaShadowFrame: {
1480 Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
1481 return NULL;
1482 }
1483 case IntrinsicHelper::SetShadowFrameEntry: {
1484 Expand_SetShadowFrameEntry(call_inst.getArgOperand(0),
1485 call_inst.getArgOperand(1));
1486 return NULL;
1487 }
1488 case IntrinsicHelper::PopShadowFrame: {
1489 Expand_PopShadowFrame();
1490 return NULL;
1491 }
1492 case IntrinsicHelper::UpdateDexPC: {
1493 Expand_UpdateDexPC(call_inst.getArgOperand(0));
1494 return NULL;
1495 }
1496 default: {
1497 const IntrinsicHelper::IntrinsicInfo& intr_info =
1498 IntrinsicHelper::GetInfo(intr_id);
1499
1500 UNIMPLEMENTED(FATAL) << "expand DexLang intrinsic: " << intr_info.name_;
1501 break;
1502 }
1503 }
1504 return NULL;
1505}
1506
1507} // anonymous namespace
1508
1509namespace art {
1510namespace compiler_llvm {
1511
1512llvm::FunctionPass*
1513CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb) {
1514 return new GBCExpanderPass(intrinsic_helper, irb);
1515}
1516
1517} // namespace compiler_llvm
1518} // namespace art