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