1 /*
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 "dex_file.h"
18 #include "dex_file-inl.h"
19 #include "driver/compiler_driver.h"
20 #include "driver/dex_compilation_unit.h"
21 #include "intrinsic_helper.h"
22 #include "ir_builder.h"
23 #include "method_reference.h"
24 #include "mirror/art_method.h"
25 #include "mirror/array.h"
26 #include "mirror/string.h"
27 #include "thread.h"
28 #include "utils_llvm.h"
29 #include "verifier/method_verifier.h"
30
31 #include "dex/compiler_ir.h"
32 #include "dex/mir_graph.h"
33 #include "dex/quick/mir_to_lir.h"
34
35 #include <llvm/ADT/STLExtras.h>
36 #include <llvm/IR/Intrinsics.h>
37 #include <llvm/IR/Metadata.h>
38 #include <llvm/Pass.h>
39 #include <llvm/Support/CFG.h>
40 #include <llvm/Support/InstIterator.h>
41
42 #include <vector>
43 #include <map>
44 #include <utility>
45
46 using ::art::kMIRIgnoreNullCheck;
47 using ::art::kMIRIgnoreRangeCheck;
48 using ::art::llvm::IRBuilder;
49 using ::art::llvm::IntrinsicHelper;
50 using ::art::llvm::JType;
51 using ::art::llvm::RuntimeSupportBuilder;
52 using ::art::llvm::kBoolean;
53 using ::art::llvm::kByte;
54 using ::art::llvm::kChar;
55 using ::art::llvm::kDouble;
56 using ::art::llvm::kFloat;
57 using ::art::llvm::kInt;
58 using ::art::llvm::kLikely;
59 using ::art::llvm::kLong;
60 using ::art::llvm::kObject;
61 using ::art::llvm::kShort;
62 using ::art::llvm::kTBAAConstJObject;
63 using ::art::llvm::kTBAAHeapArray;
64 using ::art::llvm::kTBAAHeapInstance;
65 using ::art::llvm::kTBAAHeapStatic;
66 using ::art::llvm::kTBAARegister;
67 using ::art::llvm::kTBAARuntimeInfo;
68 using ::art::llvm::kTBAAShadowFrame;
69 using ::art::llvm::kUnlikely;
70 using ::art::llvm::kVoid;
71 using ::art::llvm::runtime_support::AllocArray;
72 using ::art::llvm::runtime_support::AllocArrayWithAccessCheck;
73 using ::art::llvm::runtime_support::AllocObject;
74 using ::art::llvm::runtime_support::AllocObjectWithAccessCheck;
75 using ::art::llvm::runtime_support::CheckAndAllocArray;
76 using ::art::llvm::runtime_support::CheckAndAllocArrayWithAccessCheck;
77 using ::art::llvm::runtime_support::CheckCast;
78 using ::art::llvm::runtime_support::CheckPutArrayElement;
79 using ::art::llvm::runtime_support::FillArrayData;
80 using ::art::llvm::runtime_support::FindCatchBlock;
81 using ::art::llvm::runtime_support::FindDirectMethodWithAccessCheck;
82 using ::art::llvm::runtime_support::FindInterfaceMethod;
83 using ::art::llvm::runtime_support::FindInterfaceMethodWithAccessCheck;
84 using ::art::llvm::runtime_support::FindStaticMethodWithAccessCheck;
85 using ::art::llvm::runtime_support::FindSuperMethodWithAccessCheck;
86 using ::art::llvm::runtime_support::FindVirtualMethodWithAccessCheck;
87 using ::art::llvm::runtime_support::Get32Instance;
88 using ::art::llvm::runtime_support::Get32Static;
89 using ::art::llvm::runtime_support::Get64Instance;
90 using ::art::llvm::runtime_support::Get64Static;
91 using ::art::llvm::runtime_support::GetObjectInstance;
92 using ::art::llvm::runtime_support::GetObjectStatic;
93 using ::art::llvm::runtime_support::InitializeStaticStorage;
94 using ::art::llvm::runtime_support::InitializeType;
95 using ::art::llvm::runtime_support::InitializeTypeAndVerifyAccess;
96 using ::art::llvm::runtime_support::IsAssignable;
97 using ::art::llvm::runtime_support::ResolveString;
98 using ::art::llvm::runtime_support::RuntimeId;
99 using ::art::llvm::runtime_support::Set32Instance;
100 using ::art::llvm::runtime_support::Set32Static;
101 using ::art::llvm::runtime_support::Set64Instance;
102 using ::art::llvm::runtime_support::Set64Static;
103 using ::art::llvm::runtime_support::SetObjectInstance;
104 using ::art::llvm::runtime_support::SetObjectStatic;
105 using ::art::llvm::runtime_support::ThrowDivZeroException;
106 using ::art::llvm::runtime_support::ThrowException;
107 using ::art::llvm::runtime_support::ThrowIndexOutOfBounds;
108 using ::art::llvm::runtime_support::ThrowNullPointerException;
109 using ::art::llvm::runtime_support::ThrowStackOverflowException;
110 using ::art::llvm::runtime_support::art_d2i;
111 using ::art::llvm::runtime_support::art_d2l;
112 using ::art::llvm::runtime_support::art_f2i;
113 using ::art::llvm::runtime_support::art_f2l;
114
115 namespace art {
116 extern char RemapShorty(char shortyType);
117 } // namespace art
118
119 namespace {
120
121 class GBCExpanderPass : public llvm::FunctionPass {
122 private:
123 const IntrinsicHelper& intrinsic_helper_;
124 IRBuilder& irb_;
125
126 llvm::LLVMContext& context_;
127 RuntimeSupportBuilder& rtb_;
128
129 private:
130 llvm::AllocaInst* shadow_frame_;
131 llvm::Value* old_shadow_frame_;
132
133 private:
134 art::CompilerDriver* const driver_;
135
136 const art::DexCompilationUnit* const dex_compilation_unit_;
137
138 llvm::Function* func_;
139
140 std::vector<llvm::BasicBlock*> basic_blocks_;
141
142 std::vector<llvm::BasicBlock*> basic_block_landing_pads_;
143 llvm::BasicBlock* current_bb_;
144 std::map<llvm::BasicBlock*, std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*>>>
145 landing_pad_phi_mapping_;
146 llvm::BasicBlock* basic_block_unwind_;
147
148 // Maps each vreg to its shadow frame address.
149 std::vector<llvm::Value*> shadow_frame_vreg_addresses_;
150
151 bool changed_;
152
153 private:
154 //----------------------------------------------------------------------------
155 // Constant for GBC expansion
156 //----------------------------------------------------------------------------
157 enum IntegerShiftKind {
158 kIntegerSHL,
159 kIntegerSHR,
160 kIntegerUSHR,
161 };
162
163 private:
164 //----------------------------------------------------------------------------
165 // Helper function for GBC expansion
166 //----------------------------------------------------------------------------
167
168 llvm::Value* ExpandToRuntime(RuntimeId rt, llvm::CallInst& inst);
169
LV2UInt(llvm::Value * lv)170 uint64_t LV2UInt(llvm::Value* lv) {
171 return llvm::cast<llvm::ConstantInt>(lv)->getZExtValue();
172 }
173
LV2SInt(llvm::Value * lv)174 int64_t LV2SInt(llvm::Value* lv) {
175 return llvm::cast<llvm::ConstantInt>(lv)->getSExtValue();
176 }
177
178 private:
179 // TODO: Almost all Emit* are directly copy-n-paste from MethodCompiler.
180 // Refactor these utility functions from MethodCompiler to avoid forking.
181
182 void EmitStackOverflowCheck(llvm::Instruction* first_non_alloca);
183
184 void RewriteFunction();
185
186 void RewriteBasicBlock(llvm::BasicBlock* original_block);
187
188 void UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
189 llvm::BasicBlock* new_basic_block);
190
191
192 // Sign or zero extend category 1 types < 32bits in size to 32bits.
193 llvm::Value* SignOrZeroExtendCat1Types(llvm::Value* value, JType jty);
194
195 // Truncate category 1 types from 32bits to the given JType size.
196 llvm::Value* TruncateCat1Types(llvm::Value* value, JType jty);
197
198 //----------------------------------------------------------------------------
199 // Dex cache code generation helper function
200 //----------------------------------------------------------------------------
201 llvm::Value* EmitLoadDexCacheAddr(art::MemberOffset dex_cache_offset);
202
203 llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
204
205 llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
206
207 llvm::Value* EmitLoadDexCacheStringFieldAddr(uint32_t string_idx);
208
209 //----------------------------------------------------------------------------
210 // Code generation helper function
211 //----------------------------------------------------------------------------
212 llvm::Value* EmitLoadMethodObjectAddr();
213
214 llvm::Value* EmitLoadArrayLength(llvm::Value* array);
215
216 llvm::Value* EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx);
217
218 llvm::Value* EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,
219 llvm::Value* this_addr);
220
221 llvm::Value* EmitArrayGEP(llvm::Value* array_addr,
222 llvm::Value* index_value,
223 JType elem_jty);
224
225 //----------------------------------------------------------------------------
226 // Invoke helper function
227 //----------------------------------------------------------------------------
228 llvm::Value* EmitInvoke(llvm::CallInst& call_inst);
229
230 //----------------------------------------------------------------------------
231 // Inlining helper functions
232 //----------------------------------------------------------------------------
233 bool EmitIntrinsic(llvm::CallInst& call_inst, llvm::Value** result);
234
235 bool EmitIntrinsicStringLengthOrIsEmpty(llvm::CallInst& call_inst,
236 llvm::Value** result, bool is_empty);
237
238 private:
239 //----------------------------------------------------------------------------
240 // Expand Greenland intrinsics
241 //----------------------------------------------------------------------------
242 void Expand_TestSuspend(llvm::CallInst& call_inst);
243
244 void Expand_MarkGCCard(llvm::CallInst& call_inst);
245
246 llvm::Value* Expand_LoadStringFromDexCache(llvm::Value* string_idx_value);
247
248 llvm::Value* Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value);
249
250 void Expand_LockObject(llvm::Value* obj);
251
252 void Expand_UnlockObject(llvm::Value* obj);
253
254 llvm::Value* Expand_ArrayGet(llvm::Value* array_addr,
255 llvm::Value* index_value,
256 JType elem_jty);
257
258 void Expand_ArrayPut(llvm::Value* new_value,
259 llvm::Value* array_addr,
260 llvm::Value* index_value,
261 JType elem_jty);
262
263 void Expand_FilledNewArray(llvm::CallInst& call_inst);
264
265 llvm::Value* Expand_IGetFast(llvm::Value* field_offset_value,
266 llvm::Value* is_volatile_value,
267 llvm::Value* object_addr,
268 JType field_jty);
269
270 void Expand_IPutFast(llvm::Value* field_offset_value,
271 llvm::Value* is_volatile_value,
272 llvm::Value* object_addr,
273 llvm::Value* new_value,
274 JType field_jty);
275
276 llvm::Value* Expand_SGetFast(llvm::Value* static_storage_addr,
277 llvm::Value* field_offset_value,
278 llvm::Value* is_volatile_value,
279 JType field_jty);
280
281 void Expand_SPutFast(llvm::Value* static_storage_addr,
282 llvm::Value* field_offset_value,
283 llvm::Value* is_volatile_value,
284 llvm::Value* new_value,
285 JType field_jty);
286
287 llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
288
289 llvm::Value*
290 Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
291
292 llvm::Value*
293 Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value* vtable_idx_value,
294 llvm::Value* this_addr);
295
296 llvm::Value* Expand_Invoke(llvm::CallInst& call_inst);
297
298 llvm::Value* Expand_DivRem(llvm::CallInst& call_inst, bool is_div, JType op_jty);
299
300 void Expand_AllocaShadowFrame(llvm::Value* num_vregs_value);
301
302 void Expand_SetVReg(llvm::Value* entry_idx, llvm::Value* obj);
303
304 void Expand_PopShadowFrame();
305
306 void Expand_UpdateDexPC(llvm::Value* dex_pc_value);
307
308 //----------------------------------------------------------------------------
309 // Quick
310 //----------------------------------------------------------------------------
311
312 llvm::Value* Expand_FPCompare(llvm::Value* src1_value,
313 llvm::Value* src2_value,
314 bool gt_bias);
315
316 llvm::Value* Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value);
317
318 llvm::Value* EmitCompareResultSelection(llvm::Value* cmp_eq,
319 llvm::Value* cmp_lt);
320
321 llvm::Value* EmitLoadConstantClass(uint32_t dex_pc, uint32_t type_idx);
322 llvm::Value* EmitLoadStaticStorage(uint32_t dex_pc, uint32_t type_idx);
323
324 llvm::Value* Expand_HLIGet(llvm::CallInst& call_inst, JType field_jty);
325 void Expand_HLIPut(llvm::CallInst& call_inst, JType field_jty);
326
327 llvm::Value* Expand_HLSget(llvm::CallInst& call_inst, JType field_jty);
328 void Expand_HLSput(llvm::CallInst& call_inst, JType field_jty);
329
330 llvm::Value* Expand_HLArrayGet(llvm::CallInst& call_inst, JType field_jty);
331 void Expand_HLArrayPut(llvm::CallInst& call_inst, JType field_jty);
332
333 llvm::Value* Expand_ConstString(llvm::CallInst& call_inst);
334 llvm::Value* Expand_ConstClass(llvm::CallInst& call_inst);
335
336 void Expand_MonitorEnter(llvm::CallInst& call_inst);
337 void Expand_MonitorExit(llvm::CallInst& call_inst);
338
339 void Expand_HLCheckCast(llvm::CallInst& call_inst);
340 llvm::Value* Expand_InstanceOf(llvm::CallInst& call_inst);
341
342 llvm::Value* Expand_NewInstance(llvm::CallInst& call_inst);
343
344 llvm::Value* Expand_HLInvoke(llvm::CallInst& call_inst);
345
346 llvm::Value* Expand_OptArrayLength(llvm::CallInst& call_inst);
347 llvm::Value* Expand_NewArray(llvm::CallInst& call_inst);
348 llvm::Value* Expand_HLFilledNewArray(llvm::CallInst& call_inst);
349 void Expand_HLFillArrayData(llvm::CallInst& call_inst);
350
351 llvm::Value* EmitAllocNewArray(uint32_t dex_pc,
352 llvm::Value* array_length_value,
353 uint32_t type_idx,
354 bool is_filled_new_array);
355
356 llvm::Value* EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
357 art::InvokeType invoke_type,
358 llvm::Value* this_addr,
359 uint32_t dex_pc,
360 bool is_fast_path);
361
362 void EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr);
363
364 void EmitUpdateDexPC(uint32_t dex_pc);
365
366 void EmitGuard_DivZeroException(uint32_t dex_pc,
367 llvm::Value* denominator,
368 JType op_jty);
369
370 void EmitGuard_NullPointerException(uint32_t dex_pc, llvm::Value* object,
371 int opt_flags);
372
373 void EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
374 llvm::Value* array,
375 llvm::Value* index,
376 int opt_flags);
377
378 llvm::FunctionType* GetFunctionType(llvm::Type* ret_type, uint32_t method_idx, bool is_static);
379
380 llvm::BasicBlock* GetBasicBlock(uint32_t dex_pc);
381
382 llvm::BasicBlock* CreateBasicBlockWithDexPC(uint32_t dex_pc,
383 const char* postfix);
384
385 int32_t GetTryItemOffset(uint32_t dex_pc);
386
387 llvm::BasicBlock* GetLandingPadBasicBlock(uint32_t dex_pc);
388
389 llvm::BasicBlock* GetUnwindBasicBlock();
390
391 void EmitGuard_ExceptionLandingPad(uint32_t dex_pc);
392
393 void EmitBranchExceptionLandingPad(uint32_t dex_pc);
394
395 //----------------------------------------------------------------------------
396 // Expand Arithmetic Helper Intrinsics
397 //----------------------------------------------------------------------------
398
399 llvm::Value* Expand_IntegerShift(llvm::Value* src1_value,
400 llvm::Value* src2_value,
401 IntegerShiftKind kind,
402 JType op_jty);
403
404 public:
405 static char ID;
406
GBCExpanderPass(const IntrinsicHelper & intrinsic_helper,IRBuilder & irb,art::CompilerDriver * driver,const art::DexCompilationUnit * dex_compilation_unit)407 GBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
408 art::CompilerDriver* driver, const art::DexCompilationUnit* dex_compilation_unit)
409 : llvm::FunctionPass(ID), intrinsic_helper_(intrinsic_helper), irb_(irb),
410 context_(irb.getContext()), rtb_(irb.Runtime()),
411 shadow_frame_(NULL), old_shadow_frame_(NULL),
412 driver_(driver),
413 dex_compilation_unit_(dex_compilation_unit),
414 func_(NULL), current_bb_(NULL), basic_block_unwind_(NULL), changed_(false) {}
415
416 bool runOnFunction(llvm::Function& func);
417
418 private:
419 void InsertStackOverflowCheck(llvm::Function& func);
420
421 llvm::Value* ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
422 llvm::CallInst& call_inst);
423 };
424
425 char GBCExpanderPass::ID = 0;
426
runOnFunction(llvm::Function & func)427 bool GBCExpanderPass::runOnFunction(llvm::Function& func) {
428 VLOG(compiler) << "GBC expansion on " << func.getName().str();
429
430 // Runtime support or stub
431 if (dex_compilation_unit_ == NULL) {
432 return false;
433 }
434
435 // Setup rewrite context
436 shadow_frame_ = NULL;
437 old_shadow_frame_ = NULL;
438 func_ = &func;
439 changed_ = false; // Assume unchanged
440
441 shadow_frame_vreg_addresses_.resize(dex_compilation_unit_->GetCodeItem()->registers_size_, NULL);
442 basic_blocks_.resize(dex_compilation_unit_->GetCodeItem()->insns_size_in_code_units_);
443 basic_block_landing_pads_.resize(dex_compilation_unit_->GetCodeItem()->tries_size_, NULL);
444 basic_block_unwind_ = NULL;
445 for (llvm::Function::iterator bb_iter = func_->begin(), bb_end = func_->end();
446 bb_iter != bb_end;
447 ++bb_iter) {
448 if (bb_iter->begin()->getMetadata("DexOff") == NULL) {
449 continue;
450 }
451 uint32_t dex_pc = LV2UInt(bb_iter->begin()->getMetadata("DexOff")->getOperand(0));
452 basic_blocks_[dex_pc] = bb_iter;
453 }
454
455 // Insert stack overflow check
456 InsertStackOverflowCheck(func); // TODO: Use intrinsic.
457
458 // Rewrite the intrinsics
459 RewriteFunction();
460
461 VERIFY_LLVM_FUNCTION(func);
462
463 return changed_;
464 }
465
RewriteBasicBlock(llvm::BasicBlock * original_block)466 void GBCExpanderPass::RewriteBasicBlock(llvm::BasicBlock* original_block) {
467 llvm::BasicBlock* curr_basic_block = original_block;
468
469 llvm::BasicBlock::iterator inst_iter = original_block->begin();
470 llvm::BasicBlock::iterator inst_end = original_block->end();
471
472 while (inst_iter != inst_end) {
473 llvm::CallInst* call_inst = llvm::dyn_cast<llvm::CallInst>(inst_iter);
474 IntrinsicHelper::IntrinsicId intr_id = IntrinsicHelper::UnknownId;
475
476 if (call_inst) {
477 llvm::Function* callee_func = call_inst->getCalledFunction();
478 intr_id = intrinsic_helper_.GetIntrinsicId(callee_func);
479 }
480
481 if (intr_id == IntrinsicHelper::UnknownId) {
482 // This is not intrinsic call. Skip this instruction.
483 ++inst_iter;
484 continue;
485 }
486
487 // Rewrite the intrinsic and change the function
488 changed_ = true;
489 irb_.SetInsertPoint(inst_iter);
490
491 // Expand the intrinsic
492 if (llvm::Value* new_value = ExpandIntrinsic(intr_id, *call_inst)) {
493 inst_iter->replaceAllUsesWith(new_value);
494 }
495
496 // Remove the old intrinsic call instruction
497 llvm::BasicBlock::iterator old_inst = inst_iter++;
498 old_inst->eraseFromParent();
499
500 // Splice the instruction to the new basic block
501 llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
502 if (next_basic_block != curr_basic_block) {
503 next_basic_block->getInstList().splice(
504 irb_.GetInsertPoint(), curr_basic_block->getInstList(),
505 inst_iter, inst_end);
506 curr_basic_block = next_basic_block;
507 inst_end = curr_basic_block->end();
508 }
509 }
510 }
511
512
RewriteFunction()513 void GBCExpanderPass::RewriteFunction() {
514 size_t num_basic_blocks = func_->getBasicBlockList().size();
515 // NOTE: We are not using (bb_iter != bb_end) as the for-loop condition,
516 // because we will create new basic block while expanding the intrinsics.
517 // We only want to iterate through the input basic blocks.
518
519 landing_pad_phi_mapping_.clear();
520
521 for (llvm::Function::iterator bb_iter = func_->begin();
522 num_basic_blocks > 0; ++bb_iter, --num_basic_blocks) {
523 // Set insert point to current basic block.
524 irb_.SetInsertPoint(bb_iter);
525
526 current_bb_ = bb_iter;
527
528 // Rewrite the basic block
529 RewriteBasicBlock(bb_iter);
530
531 // Update the phi-instructions in the successor basic block
532 llvm::BasicBlock* last_block = irb_.GetInsertBlock();
533 if (last_block != bb_iter) {
534 UpdatePhiInstruction(bb_iter, last_block);
535 }
536 }
537
538 typedef std::map<llvm::PHINode*, llvm::PHINode*> HandlerPHIMap;
539 HandlerPHIMap handler_phi;
540 // Iterate every used landing pad basic block
541 for (size_t i = 0, ei = basic_block_landing_pads_.size(); i != ei; ++i) {
542 llvm::BasicBlock* lbb = basic_block_landing_pads_[i];
543 if (lbb == NULL) {
544 continue;
545 }
546
547 llvm::TerminatorInst* term_inst = lbb->getTerminator();
548 std::vector<std::pair<llvm::BasicBlock*, llvm::BasicBlock*>>& rewrite_pair
549 = landing_pad_phi_mapping_[lbb];
550 irb_.SetInsertPoint(lbb->begin());
551
552 // Iterate every succeeding basic block (catch block)
553 for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
554 succ_iter != succ_end; ++succ_iter) {
555 llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
556
557 // Iterate every phi instructions in the succeeding basic block
558 for (llvm::BasicBlock::iterator
559 inst_iter = succ_basic_block->begin(),
560 inst_end = succ_basic_block->end();
561 inst_iter != inst_end; ++inst_iter) {
562 llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
563
564 if (!phi) {
565 break; // Meet non-phi instruction. Done.
566 }
567
568 if (handler_phi[phi] == NULL) {
569 handler_phi[phi] = llvm::PHINode::Create(phi->getType(), 1);
570 }
571
572 // Create new_phi in landing pad
573 llvm::PHINode* new_phi = irb_.CreatePHI(phi->getType(), rewrite_pair.size());
574 // Insert all incoming value into new_phi by rewrite_pair
575 for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
576 llvm::BasicBlock* old_bb = rewrite_pair[j].first;
577 llvm::BasicBlock* new_bb = rewrite_pair[j].second;
578 new_phi->addIncoming(phi->getIncomingValueForBlock(old_bb), new_bb);
579 }
580 // Delete all incoming value from phi by rewrite_pair
581 for (size_t j = 0, ej = rewrite_pair.size(); j != ej; ++j) {
582 llvm::BasicBlock* old_bb = rewrite_pair[j].first;
583 int old_bb_idx = phi->getBasicBlockIndex(old_bb);
584 if (old_bb_idx >= 0) {
585 phi->removeIncomingValue(old_bb_idx, false);
586 }
587 }
588 // Insert new_phi into new handler phi
589 handler_phi[phi]->addIncoming(new_phi, lbb);
590 }
591 }
592 }
593
594 // Replace all handler phi
595 // We can't just use the old handler phi, because some exception edges will disappear after we
596 // compute fast-path.
597 for (HandlerPHIMap::iterator it = handler_phi.begin(); it != handler_phi.end(); ++it) {
598 llvm::PHINode* old_phi = it->first;
599 llvm::PHINode* new_phi = it->second;
600 new_phi->insertBefore(old_phi);
601 old_phi->replaceAllUsesWith(new_phi);
602 old_phi->eraseFromParent();
603 }
604 }
605
UpdatePhiInstruction(llvm::BasicBlock * old_basic_block,llvm::BasicBlock * new_basic_block)606 void GBCExpanderPass::UpdatePhiInstruction(llvm::BasicBlock* old_basic_block,
607 llvm::BasicBlock* new_basic_block) {
608 llvm::TerminatorInst* term_inst = new_basic_block->getTerminator();
609
610 if (!term_inst) {
611 return; // No terminating instruction in new_basic_block. Nothing to do.
612 }
613
614 // Iterate every succeeding basic block
615 for (unsigned succ_iter = 0, succ_end = term_inst->getNumSuccessors();
616 succ_iter != succ_end; ++succ_iter) {
617 llvm::BasicBlock* succ_basic_block = term_inst->getSuccessor(succ_iter);
618
619 // Iterate every phi instructions in the succeeding basic block
620 for (llvm::BasicBlock::iterator
621 inst_iter = succ_basic_block->begin(),
622 inst_end = succ_basic_block->end();
623 inst_iter != inst_end; ++inst_iter) {
624 llvm::PHINode *phi = llvm::dyn_cast<llvm::PHINode>(inst_iter);
625
626 if (!phi) {
627 break; // Meet non-phi instruction. Done.
628 }
629
630 // Update the incoming block of this phi instruction
631 for (llvm::PHINode::block_iterator
632 ibb_iter = phi->block_begin(), ibb_end = phi->block_end();
633 ibb_iter != ibb_end; ++ibb_iter) {
634 if (*ibb_iter == old_basic_block) {
635 *ibb_iter = new_basic_block;
636 }
637 }
638 }
639 }
640 }
641
ExpandToRuntime(RuntimeId rt,llvm::CallInst & inst)642 llvm::Value* GBCExpanderPass::ExpandToRuntime(RuntimeId rt, llvm::CallInst& inst) {
643 // Some GBC intrinsic can directly replace with IBC runtime. "Directly" means
644 // the arguments passed to the GBC intrinsic are as the same as IBC runtime
645 // function, therefore only called function is needed to change.
646 unsigned num_args = inst.getNumArgOperands();
647
648 if (num_args <= 0) {
649 return irb_.CreateCall(irb_.GetRuntime(rt));
650 } else {
651 std::vector<llvm::Value*> args;
652 for (unsigned i = 0; i < num_args; i++) {
653 args.push_back(inst.getArgOperand(i));
654 }
655
656 return irb_.CreateCall(irb_.GetRuntime(rt), args);
657 }
658 }
659
660 void
EmitStackOverflowCheck(llvm::Instruction * first_non_alloca)661 GBCExpanderPass::EmitStackOverflowCheck(llvm::Instruction* first_non_alloca) {
662 llvm::Function* func = first_non_alloca->getParent()->getParent();
663 llvm::Module* module = func->getParent();
664
665 // Call llvm intrinsic function to get frame address.
666 llvm::Function* frameaddress =
667 llvm::Intrinsic::getDeclaration(module, llvm::Intrinsic::frameaddress);
668
669 // The type of llvm::frameaddress is: i8* @llvm.frameaddress(i32)
670 llvm::Value* frame_address = irb_.CreateCall(frameaddress, irb_.getInt32(0));
671
672 // Cast i8* to int
673 frame_address = irb_.CreatePtrToInt(frame_address, irb_.getPtrEquivIntTy());
674
675 // Get thread.stack_end_
676 llvm::Value* stack_end =
677 irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::StackEndOffset().Int32Value(),
678 irb_.getPtrEquivIntTy(),
679 kTBAARuntimeInfo);
680
681 // Check the frame address < thread.stack_end_ ?
682 llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
683
684 llvm::BasicBlock* block_exception =
685 llvm::BasicBlock::Create(context_, "stack_overflow", func);
686
687 llvm::BasicBlock* block_continue =
688 llvm::BasicBlock::Create(context_, "stack_overflow_cont", func);
689
690 irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
691
692 // If stack overflow, throw exception.
693 irb_.SetInsertPoint(block_exception);
694 irb_.CreateCall(irb_.GetRuntime(ThrowStackOverflowException));
695
696 // Unwind.
697 llvm::Type* ret_type = func->getReturnType();
698 if (ret_type->isVoidTy()) {
699 irb_.CreateRetVoid();
700 } else {
701 // The return value is ignored when there's an exception. MethodCompiler
702 // returns zero value under the the corresponding return type in this case.
703 // GBCExpander returns LLVM undef value here for brevity
704 irb_.CreateRet(llvm::UndefValue::get(ret_type));
705 }
706
707 irb_.SetInsertPoint(block_continue);
708 }
709
EmitLoadDexCacheAddr(art::MemberOffset offset)710 llvm::Value* GBCExpanderPass::EmitLoadDexCacheAddr(art::MemberOffset offset) {
711 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
712
713 return irb_.LoadFromObjectOffset(method_object_addr,
714 offset.Int32Value(),
715 irb_.getJObjectTy(),
716 kTBAAConstJObject);
717 }
718
719 llvm::Value*
EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx)720 GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
721 llvm::Value* resolved_type_dex_cache_addr =
722 EmitLoadDexCacheAddr(art::mirror::ArtMethod::DexCacheResolvedTypesOffset());
723
724 llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
725
726 return EmitArrayGEP(resolved_type_dex_cache_addr, type_idx_value, kObject);
727 }
728
729 llvm::Value* GBCExpanderPass::
EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx)730 EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx) {
731 llvm::Value* resolved_method_dex_cache_addr =
732 EmitLoadDexCacheAddr(art::mirror::ArtMethod::DexCacheResolvedMethodsOffset());
733
734 llvm::Value* method_idx_value = irb_.getPtrEquivInt(method_idx);
735
736 return EmitArrayGEP(resolved_method_dex_cache_addr, method_idx_value, kObject);
737 }
738
739 llvm::Value* GBCExpanderPass::
EmitLoadDexCacheStringFieldAddr(uint32_t string_idx)740 EmitLoadDexCacheStringFieldAddr(uint32_t string_idx) {
741 llvm::Value* string_dex_cache_addr =
742 EmitLoadDexCacheAddr(art::mirror::ArtMethod::DexCacheStringsOffset());
743
744 llvm::Value* string_idx_value = irb_.getPtrEquivInt(string_idx);
745
746 return EmitArrayGEP(string_dex_cache_addr, string_idx_value, kObject);
747 }
748
EmitLoadMethodObjectAddr()749 llvm::Value* GBCExpanderPass::EmitLoadMethodObjectAddr() {
750 llvm::Function* parent_func = irb_.GetInsertBlock()->getParent();
751 return parent_func->arg_begin();
752 }
753
EmitLoadArrayLength(llvm::Value * array)754 llvm::Value* GBCExpanderPass::EmitLoadArrayLength(llvm::Value* array) {
755 // Load array length
756 return irb_.LoadFromObjectOffset(array,
757 art::mirror::Array::LengthOffset().Int32Value(),
758 irb_.getJIntTy(),
759 kTBAAConstJObject);
760 }
761
762 llvm::Value*
EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx)763 GBCExpanderPass::EmitLoadSDCalleeMethodObjectAddr(uint32_t callee_method_idx) {
764 llvm::Value* callee_method_object_field_addr =
765 EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
766
767 return irb_.CreateLoad(callee_method_object_field_addr, kTBAARuntimeInfo);
768 }
769
770 llvm::Value* GBCExpanderPass::
EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx,llvm::Value * this_addr)771 EmitLoadVirtualCalleeMethodObjectAddr(int vtable_idx, llvm::Value* this_addr) {
772 // Load class object of *this* pointer
773 llvm::Value* class_object_addr =
774 irb_.LoadFromObjectOffset(this_addr,
775 art::mirror::Object::ClassOffset().Int32Value(),
776 irb_.getJObjectTy(),
777 kTBAAConstJObject);
778
779 // Load vtable address
780 llvm::Value* vtable_addr =
781 irb_.LoadFromObjectOffset(class_object_addr,
782 art::mirror::Class::VTableOffset().Int32Value(),
783 irb_.getJObjectTy(),
784 kTBAAConstJObject);
785
786 // Load callee method object
787 llvm::Value* vtable_idx_value =
788 irb_.getPtrEquivInt(static_cast<uint64_t>(vtable_idx));
789
790 llvm::Value* method_field_addr =
791 EmitArrayGEP(vtable_addr, vtable_idx_value, kObject);
792
793 return irb_.CreateLoad(method_field_addr, kTBAAConstJObject);
794 }
795
796 // Emit Array GetElementPtr
EmitArrayGEP(llvm::Value * array_addr,llvm::Value * index_value,JType elem_jty)797 llvm::Value* GBCExpanderPass::EmitArrayGEP(llvm::Value* array_addr,
798 llvm::Value* index_value,
799 JType elem_jty) {
800 int data_offset;
801 if (elem_jty == kLong || elem_jty == kDouble ||
802 (elem_jty == kObject && sizeof(uint64_t) == sizeof(art::mirror::Object*))) {
803 data_offset = art::mirror::Array::DataOffset(sizeof(int64_t)).Int32Value();
804 } else {
805 data_offset = art::mirror::Array::DataOffset(sizeof(int32_t)).Int32Value();
806 }
807
808 llvm::Constant* data_offset_value =
809 irb_.getPtrEquivInt(data_offset);
810
811 llvm::Type* elem_type = irb_.getJType(elem_jty);
812
813 llvm::Value* array_data_addr =
814 irb_.CreatePtrDisp(array_addr, data_offset_value,
815 elem_type->getPointerTo());
816
817 return irb_.CreateGEP(array_data_addr, index_value);
818 }
819
EmitInvoke(llvm::CallInst & call_inst)820 llvm::Value* GBCExpanderPass::EmitInvoke(llvm::CallInst& call_inst) {
821 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
822 art::InvokeType invoke_type =
823 static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
824 bool is_static = (invoke_type == art::kStatic);
825 art::MethodReference target_method(dex_compilation_unit_->GetDexFile(),
826 LV2UInt(call_inst.getArgOperand(1)));
827
828 // Load *this* actual parameter
829 llvm::Value* this_addr = (!is_static) ? call_inst.getArgOperand(3) : NULL;
830
831 // Compute invoke related information for compiler decision
832 int vtable_idx = -1;
833 uintptr_t direct_code = 0;
834 uintptr_t direct_method = 0;
835 bool is_fast_path = driver_->ComputeInvokeInfo(dex_compilation_unit_, dex_pc,
836 true, true,
837 &invoke_type, &target_method,
838 &vtable_idx,
839 &direct_code, &direct_method);
840 // Load the method object
841 llvm::Value* callee_method_object_addr = NULL;
842
843 if (!is_fast_path) {
844 callee_method_object_addr =
845 EmitCallRuntimeForCalleeMethodObjectAddr(target_method.dex_method_index, invoke_type,
846 this_addr, dex_pc, is_fast_path);
847 } else {
848 switch (invoke_type) {
849 case art::kStatic:
850 case art::kDirect:
851 if (direct_method != 0u &&
852 direct_method != static_cast<uintptr_t>(-1)) {
853 callee_method_object_addr =
854 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_method),
855 irb_.getJObjectTy());
856 } else {
857 callee_method_object_addr =
858 EmitLoadSDCalleeMethodObjectAddr(target_method.dex_method_index);
859 }
860 break;
861
862 case art::kVirtual:
863 DCHECK_NE(vtable_idx, -1);
864 callee_method_object_addr =
865 EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
866 break;
867
868 case art::kSuper:
869 LOG(FATAL) << "invoke-super should be promoted to invoke-direct in "
870 "the fast path.";
871 break;
872
873 case art::kInterface:
874 callee_method_object_addr =
875 EmitCallRuntimeForCalleeMethodObjectAddr(target_method.dex_method_index,
876 invoke_type, this_addr,
877 dex_pc, is_fast_path);
878 break;
879 }
880 }
881
882 // Load the actual parameter
883 std::vector<llvm::Value*> args;
884
885 args.push_back(callee_method_object_addr); // method object for callee
886
887 for (uint32_t i = 3; i < call_inst.getNumArgOperands(); ++i) {
888 args.push_back(call_inst.getArgOperand(i));
889 }
890
891 llvm::Value* code_addr;
892 llvm::Type* func_type = GetFunctionType(call_inst.getType(),
893 target_method.dex_method_index, is_static);
894 if (direct_code != 0u && direct_code != static_cast<uintptr_t>(-1)) {
895 code_addr =
896 irb_.CreateIntToPtr(irb_.getPtrEquivInt(direct_code),
897 func_type->getPointerTo());
898 } else {
899 code_addr =
900 irb_.LoadFromObjectOffset(callee_method_object_addr,
901 art::mirror::ArtMethod::EntryPointFromPortableCompiledCodeOffset().Int32Value(),
902 func_type->getPointerTo(), kTBAARuntimeInfo);
903 }
904
905 // Invoke callee
906 EmitUpdateDexPC(dex_pc);
907 llvm::Value* retval = irb_.CreateCall(code_addr, args);
908 EmitGuard_ExceptionLandingPad(dex_pc);
909
910 return retval;
911 }
912
EmitIntrinsic(llvm::CallInst & call_inst,llvm::Value ** result)913 bool GBCExpanderPass::EmitIntrinsic(llvm::CallInst& call_inst,
914 llvm::Value** result) {
915 DCHECK(result != NULL);
916
917 uint32_t callee_method_idx = LV2UInt(call_inst.getArgOperand(1));
918 std::string callee_method_name(
919 PrettyMethod(callee_method_idx, *dex_compilation_unit_->GetDexFile()));
920
921 if (callee_method_name == "int java.lang.String.length()") {
922 return EmitIntrinsicStringLengthOrIsEmpty(call_inst, result,
923 false /* is_empty */);
924 }
925 if (callee_method_name == "boolean java.lang.String.isEmpty()") {
926 return EmitIntrinsicStringLengthOrIsEmpty(call_inst, result,
927 true /* is_empty */);
928 }
929
930 *result = NULL;
931 return false;
932 }
933
EmitIntrinsicStringLengthOrIsEmpty(llvm::CallInst & call_inst,llvm::Value ** result,bool is_empty)934 bool GBCExpanderPass::EmitIntrinsicStringLengthOrIsEmpty(llvm::CallInst& call_inst,
935 llvm::Value** result,
936 bool is_empty) {
937 art::InvokeType invoke_type =
938 static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
939 DCHECK_NE(invoke_type, art::kStatic);
940 DCHECK_EQ(call_inst.getNumArgOperands(), 4U);
941
942 llvm::Value* this_object = call_inst.getArgOperand(3);
943 llvm::Value* string_count =
944 irb_.LoadFromObjectOffset(this_object,
945 art::mirror::String::CountOffset().Int32Value(),
946 irb_.getJIntTy(),
947 kTBAAConstJObject);
948 if (is_empty) {
949 llvm::Value* count_equals_zero = irb_.CreateICmpEQ(string_count,
950 irb_.getJInt(0));
951 llvm::Value* is_empty = irb_.CreateSelect(count_equals_zero,
952 irb_.getJBoolean(true),
953 irb_.getJBoolean(false));
954 is_empty = SignOrZeroExtendCat1Types(is_empty, kBoolean);
955 *result = is_empty;
956 } else {
957 *result = string_count;
958 }
959 return true;
960 }
961
Expand_TestSuspend(llvm::CallInst & call_inst)962 void GBCExpanderPass::Expand_TestSuspend(llvm::CallInst& call_inst) {
963 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
964
965 llvm::Value* suspend_count =
966 irb_.Runtime().EmitLoadFromThreadOffset(art::Thread::ThreadFlagsOffset().Int32Value(),
967 irb_.getInt16Ty(),
968 kTBAARuntimeInfo);
969 llvm::Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getInt16(0));
970
971 llvm::BasicBlock* basic_block_suspend = CreateBasicBlockWithDexPC(dex_pc, "suspend");
972 llvm::BasicBlock* basic_block_cont = CreateBasicBlockWithDexPC(dex_pc, "suspend_cont");
973
974 irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_cont, kUnlikely);
975
976 irb_.SetInsertPoint(basic_block_suspend);
977 if (dex_pc != art::DexFile::kDexNoIndex) {
978 EmitUpdateDexPC(dex_pc);
979 }
980 irb_.Runtime().EmitTestSuspend();
981
982 llvm::BasicBlock* basic_block_exception = CreateBasicBlockWithDexPC(dex_pc, "exception");
983 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
984 irb_.CreateCondBr(exception_pending, basic_block_exception, basic_block_cont, kUnlikely);
985
986 irb_.SetInsertPoint(basic_block_exception);
987 llvm::Type* ret_type = call_inst.getParent()->getParent()->getReturnType();
988 if (ret_type->isVoidTy()) {
989 irb_.CreateRetVoid();
990 } else {
991 // The return value is ignored when there's an exception.
992 irb_.CreateRet(llvm::UndefValue::get(ret_type));
993 }
994
995 irb_.SetInsertPoint(basic_block_cont);
996 return;
997 }
998
Expand_MarkGCCard(llvm::CallInst & call_inst)999 void GBCExpanderPass::Expand_MarkGCCard(llvm::CallInst& call_inst) {
1000 irb_.Runtime().EmitMarkGCCard(call_inst.getArgOperand(0), call_inst.getArgOperand(1));
1001 return;
1002 }
1003
1004 llvm::Value*
Expand_LoadStringFromDexCache(llvm::Value * string_idx_value)1005 GBCExpanderPass::Expand_LoadStringFromDexCache(llvm::Value* string_idx_value) {
1006 uint32_t string_idx =
1007 llvm::cast<llvm::ConstantInt>(string_idx_value)->getZExtValue();
1008
1009 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
1010
1011 return irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
1012 }
1013
1014 llvm::Value*
Expand_LoadTypeFromDexCache(llvm::Value * type_idx_value)1015 GBCExpanderPass::Expand_LoadTypeFromDexCache(llvm::Value* type_idx_value) {
1016 uint32_t type_idx =
1017 llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
1018
1019 llvm::Value* type_field_addr =
1020 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
1021
1022 return irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
1023 }
1024
Expand_LockObject(llvm::Value * obj)1025 void GBCExpanderPass::Expand_LockObject(llvm::Value* obj) {
1026 rtb_.EmitLockObject(obj);
1027 return;
1028 }
1029
Expand_UnlockObject(llvm::Value * obj)1030 void GBCExpanderPass::Expand_UnlockObject(llvm::Value* obj) {
1031 rtb_.EmitUnlockObject(obj);
1032 return;
1033 }
1034
Expand_ArrayGet(llvm::Value * array_addr,llvm::Value * index_value,JType elem_jty)1035 llvm::Value* GBCExpanderPass::Expand_ArrayGet(llvm::Value* array_addr,
1036 llvm::Value* index_value,
1037 JType elem_jty) {
1038 llvm::Value* array_elem_addr =
1039 EmitArrayGEP(array_addr, index_value, elem_jty);
1040
1041 return irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
1042 }
1043
Expand_ArrayPut(llvm::Value * new_value,llvm::Value * array_addr,llvm::Value * index_value,JType elem_jty)1044 void GBCExpanderPass::Expand_ArrayPut(llvm::Value* new_value,
1045 llvm::Value* array_addr,
1046 llvm::Value* index_value,
1047 JType elem_jty) {
1048 llvm::Value* array_elem_addr =
1049 EmitArrayGEP(array_addr, index_value, elem_jty);
1050
1051 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
1052
1053 return;
1054 }
1055
Expand_FilledNewArray(llvm::CallInst & call_inst)1056 void GBCExpanderPass::Expand_FilledNewArray(llvm::CallInst& call_inst) {
1057 // Most of the codes refer to MethodCompiler::EmitInsn_FilledNewArray
1058 llvm::Value* array = call_inst.getArgOperand(0);
1059
1060 uint32_t element_jty =
1061 llvm::cast<llvm::ConstantInt>(call_inst.getArgOperand(1))->getZExtValue();
1062
1063 DCHECK_GT(call_inst.getNumArgOperands(), 2U);
1064 unsigned num_elements = (call_inst.getNumArgOperands() - 2);
1065
1066 bool is_elem_int_ty = (static_cast<JType>(element_jty) == kInt);
1067
1068 uint32_t alignment;
1069 llvm::Constant* elem_size;
1070 llvm::PointerType* field_type;
1071
1072 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
1073 // as the element, thus we are only checking 2 cases: primitive int and
1074 // non-primitive type.
1075 if (is_elem_int_ty) {
1076 alignment = sizeof(int32_t);
1077 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
1078 field_type = irb_.getJIntTy()->getPointerTo();
1079 } else {
1080 alignment = irb_.getSizeOfPtrEquivInt();
1081 elem_size = irb_.getSizeOfPtrEquivIntValue();
1082 field_type = irb_.getJObjectTy()->getPointerTo();
1083 }
1084
1085 llvm::Value* data_field_offset =
1086 irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
1087
1088 llvm::Value* data_field_addr =
1089 irb_.CreatePtrDisp(array, data_field_offset, field_type);
1090
1091 for (unsigned i = 0; i < num_elements; ++i) {
1092 // Values to fill the array begin at the 3rd argument
1093 llvm::Value* reg_value = call_inst.getArgOperand(2 + i);
1094
1095 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
1096
1097 data_field_addr =
1098 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
1099 }
1100
1101 return;
1102 }
1103
Expand_IGetFast(llvm::Value * field_offset_value,llvm::Value *,llvm::Value * object_addr,JType field_jty)1104 llvm::Value* GBCExpanderPass::Expand_IGetFast(llvm::Value* field_offset_value,
1105 llvm::Value* /*is_volatile_value*/,
1106 llvm::Value* object_addr,
1107 JType field_jty) {
1108 int field_offset =
1109 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
1110
1111 DCHECK_GE(field_offset, 0);
1112
1113 llvm::PointerType* field_type =
1114 irb_.getJType(field_jty)->getPointerTo();
1115
1116 field_offset_value = irb_.getPtrEquivInt(field_offset);
1117
1118 llvm::Value* field_addr =
1119 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1120
1121 // TODO: Check is_volatile. We need to generate atomic load instruction
1122 // when is_volatile is true.
1123 return irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
1124 }
1125
Expand_IPutFast(llvm::Value * field_offset_value,llvm::Value *,llvm::Value * object_addr,llvm::Value * new_value,JType field_jty)1126 void GBCExpanderPass::Expand_IPutFast(llvm::Value* field_offset_value,
1127 llvm::Value* /* is_volatile_value */,
1128 llvm::Value* object_addr,
1129 llvm::Value* new_value,
1130 JType field_jty) {
1131 int field_offset =
1132 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
1133
1134 DCHECK_GE(field_offset, 0);
1135
1136 llvm::PointerType* field_type =
1137 irb_.getJType(field_jty)->getPointerTo();
1138
1139 field_offset_value = irb_.getPtrEquivInt(field_offset);
1140
1141 llvm::Value* field_addr =
1142 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1143
1144 // TODO: Check is_volatile. We need to generate atomic store instruction
1145 // when is_volatile is true.
1146 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
1147
1148 return;
1149 }
1150
Expand_SGetFast(llvm::Value * static_storage_addr,llvm::Value * field_offset_value,llvm::Value *,JType field_jty)1151 llvm::Value* GBCExpanderPass::Expand_SGetFast(llvm::Value* static_storage_addr,
1152 llvm::Value* field_offset_value,
1153 llvm::Value* /*is_volatile_value*/,
1154 JType field_jty) {
1155 int field_offset =
1156 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
1157
1158 DCHECK_GE(field_offset, 0);
1159
1160 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1161
1162 llvm::Value* static_field_addr =
1163 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
1164 irb_.getJType(field_jty)->getPointerTo());
1165
1166 // TODO: Check is_volatile. We need to generate atomic store instruction
1167 // when is_volatile is true.
1168 return irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
1169 }
1170
Expand_SPutFast(llvm::Value * static_storage_addr,llvm::Value * field_offset_value,llvm::Value *,llvm::Value * new_value,JType field_jty)1171 void GBCExpanderPass::Expand_SPutFast(llvm::Value* static_storage_addr,
1172 llvm::Value* field_offset_value,
1173 llvm::Value* /* is_volatile_value */,
1174 llvm::Value* new_value,
1175 JType field_jty) {
1176 int field_offset =
1177 llvm::cast<llvm::ConstantInt>(field_offset_value)->getSExtValue();
1178
1179 DCHECK_GE(field_offset, 0);
1180
1181 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset);
1182
1183 llvm::Value* static_field_addr =
1184 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
1185 irb_.getJType(field_jty)->getPointerTo());
1186
1187 // TODO: Check is_volatile. We need to generate atomic store instruction
1188 // when is_volatile is true.
1189 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
1190
1191 return;
1192 }
1193
1194 llvm::Value*
Expand_LoadDeclaringClassSSB(llvm::Value * method_object_addr)1195 GBCExpanderPass::Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr) {
1196 return irb_.LoadFromObjectOffset(method_object_addr,
1197 art::mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
1198 irb_.getJObjectTy(),
1199 kTBAAConstJObject);
1200 }
1201
1202 llvm::Value*
Expand_GetSDCalleeMethodObjAddrFast(llvm::Value * callee_method_idx_value)1203 GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
1204 uint32_t callee_method_idx =
1205 llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
1206
1207 return EmitLoadSDCalleeMethodObjectAddr(callee_method_idx);
1208 }
1209
Expand_GetVirtualCalleeMethodObjAddrFast(llvm::Value * vtable_idx_value,llvm::Value * this_addr)1210 llvm::Value* GBCExpanderPass::Expand_GetVirtualCalleeMethodObjAddrFast(
1211 llvm::Value* vtable_idx_value,
1212 llvm::Value* this_addr) {
1213 int vtable_idx =
1214 llvm::cast<llvm::ConstantInt>(vtable_idx_value)->getSExtValue();
1215
1216 return EmitLoadVirtualCalleeMethodObjectAddr(vtable_idx, this_addr);
1217 }
1218
Expand_Invoke(llvm::CallInst & call_inst)1219 llvm::Value* GBCExpanderPass::Expand_Invoke(llvm::CallInst& call_inst) {
1220 // Most of the codes refer to MethodCompiler::EmitInsn_Invoke
1221 llvm::Value* callee_method_object_addr = call_inst.getArgOperand(0);
1222 unsigned num_args = call_inst.getNumArgOperands();
1223 llvm::Type* ret_type = call_inst.getType();
1224
1225 // Determine the function type of the callee method
1226 std::vector<llvm::Type*> args_type;
1227 std::vector<llvm::Value*> args;
1228 for (unsigned i = 0; i < num_args; i++) {
1229 args.push_back(call_inst.getArgOperand(i));
1230 args_type.push_back(args[i]->getType());
1231 }
1232
1233 llvm::FunctionType* callee_method_type =
1234 llvm::FunctionType::get(ret_type, args_type, false);
1235
1236 llvm::Value* code_addr =
1237 irb_.LoadFromObjectOffset(callee_method_object_addr,
1238 art::mirror::ArtMethod::EntryPointFromPortableCompiledCodeOffset().Int32Value(),
1239 callee_method_type->getPointerTo(),
1240 kTBAARuntimeInfo);
1241
1242 // Invoke callee
1243 llvm::Value* retval = irb_.CreateCall(code_addr, args);
1244
1245 return retval;
1246 }
1247
Expand_DivRem(llvm::CallInst & call_inst,bool is_div,JType op_jty)1248 llvm::Value* GBCExpanderPass::Expand_DivRem(llvm::CallInst& call_inst,
1249 bool is_div, JType op_jty) {
1250 llvm::Value* dividend = call_inst.getArgOperand(0);
1251 llvm::Value* divisor = call_inst.getArgOperand(1);
1252 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1253 EmitGuard_DivZeroException(dex_pc, divisor, op_jty);
1254 // Most of the codes refer to MethodCompiler::EmitIntDivRemResultComputation
1255
1256 // Check the special case: MININT / -1 = MININT
1257 // That case will cause overflow, which is undefined behavior in llvm.
1258 // So we check the divisor is -1 or not, if the divisor is -1, we do
1259 // the special path to avoid undefined behavior.
1260 llvm::Type* op_type = irb_.getJType(op_jty);
1261 llvm::Value* zero = irb_.getJZero(op_jty);
1262 llvm::Value* neg_one = llvm::ConstantInt::getSigned(op_type, -1);
1263
1264 llvm::Function* parent = irb_.GetInsertBlock()->getParent();
1265 llvm::BasicBlock* eq_neg_one = llvm::BasicBlock::Create(context_, "", parent);
1266 llvm::BasicBlock* ne_neg_one = llvm::BasicBlock::Create(context_, "", parent);
1267 llvm::BasicBlock* neg_one_cont =
1268 llvm::BasicBlock::Create(context_, "", parent);
1269
1270 llvm::Value* is_equal_neg_one = irb_.CreateICmpEQ(divisor, neg_one);
1271 irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
1272
1273 // If divisor == -1
1274 irb_.SetInsertPoint(eq_neg_one);
1275 llvm::Value* eq_result;
1276 if (is_div) {
1277 // We can just change from "dividend div -1" to "neg dividend". The sub
1278 // don't care the sign/unsigned because of two's complement representation.
1279 // And the behavior is what we want:
1280 // -(2^n) (2^n)-1
1281 // MININT < k <= MAXINT -> mul k -1 = -k
1282 // MININT == k -> mul k -1 = k
1283 //
1284 // LLVM use sub to represent 'neg'
1285 eq_result = irb_.CreateSub(zero, dividend);
1286 } else {
1287 // Everything modulo -1 will be 0.
1288 eq_result = zero;
1289 }
1290 irb_.CreateBr(neg_one_cont);
1291
1292 // If divisor != -1, just do the division.
1293 irb_.SetInsertPoint(ne_neg_one);
1294 llvm::Value* ne_result;
1295 if (is_div) {
1296 ne_result = irb_.CreateSDiv(dividend, divisor);
1297 } else {
1298 ne_result = irb_.CreateSRem(dividend, divisor);
1299 }
1300 irb_.CreateBr(neg_one_cont);
1301
1302 irb_.SetInsertPoint(neg_one_cont);
1303 llvm::PHINode* result = irb_.CreatePHI(op_type, 2);
1304 result->addIncoming(eq_result, eq_neg_one);
1305 result->addIncoming(ne_result, ne_neg_one);
1306
1307 return result;
1308 }
1309
Expand_AllocaShadowFrame(llvm::Value * num_vregs_value)1310 void GBCExpanderPass::Expand_AllocaShadowFrame(llvm::Value* num_vregs_value) {
1311 // Most of the codes refer to MethodCompiler::EmitPrologueAllocShadowFrame and
1312 // MethodCompiler::EmitPushShadowFrame
1313 uint16_t num_vregs =
1314 llvm::cast<llvm::ConstantInt>(num_vregs_value)->getZExtValue();
1315
1316 llvm::StructType* shadow_frame_type =
1317 irb_.getShadowFrameTy(num_vregs);
1318
1319 // Create allocas at the start of entry block.
1320 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
1321 llvm::BasicBlock* entry_block = &func_->front();
1322 irb_.SetInsertPoint(&entry_block->front());
1323
1324 shadow_frame_ = irb_.CreateAlloca(shadow_frame_type);
1325
1326 // Alloca a pointer to old shadow frame
1327 old_shadow_frame_ =
1328 irb_.CreateAlloca(shadow_frame_type->getElementType(0)->getPointerTo());
1329
1330 irb_.restoreIP(irb_ip_original);
1331
1332 // Push the shadow frame
1333 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1334
1335 llvm::Value* shadow_frame_upcast =
1336 irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
1337
1338 llvm::Value* result = rtb_.EmitPushShadowFrame(shadow_frame_upcast,
1339 method_object_addr,
1340 num_vregs);
1341
1342 irb_.CreateStore(result, old_shadow_frame_, kTBAARegister);
1343
1344 return;
1345 }
1346
Expand_SetVReg(llvm::Value * entry_idx,llvm::Value * value)1347 void GBCExpanderPass::Expand_SetVReg(llvm::Value* entry_idx,
1348 llvm::Value* value) {
1349 unsigned vreg_idx = LV2UInt(entry_idx);
1350 DCHECK_LT(vreg_idx, dex_compilation_unit_->GetCodeItem()->registers_size_);
1351
1352 llvm::Value* vreg_addr = shadow_frame_vreg_addresses_[vreg_idx];
1353 if (UNLIKELY(vreg_addr == NULL)) {
1354 DCHECK(shadow_frame_ != NULL);
1355
1356 llvm::Value* gep_index[] = {
1357 irb_.getInt32(0), // No pointer displacement
1358 irb_.getInt32(1), // VRegs
1359 entry_idx // Pointer field
1360 };
1361
1362 // A shadow frame address must dominate every use in the function so we
1363 // place it in the entry block right after the allocas.
1364 llvm::BasicBlock::iterator first_non_alloca = func_->getEntryBlock().begin();
1365 while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
1366 ++first_non_alloca;
1367 }
1368
1369 llvm::IRBuilderBase::InsertPoint ip = irb_.saveIP();
1370 irb_.SetInsertPoint(static_cast<llvm::Instruction*>(first_non_alloca));
1371 vreg_addr = irb_.CreateGEP(shadow_frame_, gep_index);
1372 shadow_frame_vreg_addresses_[vreg_idx] = vreg_addr;
1373 irb_.restoreIP(ip);
1374 }
1375
1376 irb_.CreateStore(value,
1377 irb_.CreateBitCast(vreg_addr, value->getType()->getPointerTo()),
1378 kTBAAShadowFrame);
1379 return;
1380 }
1381
Expand_PopShadowFrame()1382 void GBCExpanderPass::Expand_PopShadowFrame() {
1383 if (old_shadow_frame_ == NULL) {
1384 return;
1385 }
1386 rtb_.EmitPopShadowFrame(irb_.CreateLoad(old_shadow_frame_, kTBAARegister));
1387 return;
1388 }
1389
Expand_UpdateDexPC(llvm::Value * dex_pc_value)1390 void GBCExpanderPass::Expand_UpdateDexPC(llvm::Value* dex_pc_value) {
1391 irb_.StoreToObjectOffset(shadow_frame_,
1392 art::ShadowFrame::DexPCOffset(),
1393 dex_pc_value,
1394 kTBAAShadowFrame);
1395 return;
1396 }
1397
InsertStackOverflowCheck(llvm::Function & func)1398 void GBCExpanderPass::InsertStackOverflowCheck(llvm::Function& func) {
1399 // All alloca instructions are generated in the first basic block of the
1400 // function, and there are no alloca instructions after the first non-alloca
1401 // instruction.
1402
1403 llvm::BasicBlock* first_basic_block = &func.front();
1404
1405 // Look for first non-alloca instruction
1406 llvm::BasicBlock::iterator first_non_alloca = first_basic_block->begin();
1407 while (llvm::isa<llvm::AllocaInst>(first_non_alloca)) {
1408 ++first_non_alloca;
1409 }
1410
1411 irb_.SetInsertPoint(first_non_alloca);
1412
1413 // Insert stack overflow check codes before first_non_alloca (i.e., after all
1414 // alloca instructions)
1415 EmitStackOverflowCheck(&*first_non_alloca);
1416
1417 irb_.Runtime().EmitTestSuspend();
1418
1419 llvm::BasicBlock* next_basic_block = irb_.GetInsertBlock();
1420 if (next_basic_block != first_basic_block) {
1421 // Splice the rest of the instruction to the continuing basic block
1422 next_basic_block->getInstList().splice(
1423 irb_.GetInsertPoint(), first_basic_block->getInstList(),
1424 first_non_alloca, first_basic_block->end());
1425
1426 // Rewrite the basic block
1427 RewriteBasicBlock(next_basic_block);
1428
1429 // Update the phi-instructions in the successor basic block
1430 UpdatePhiInstruction(first_basic_block, irb_.GetInsertBlock());
1431 }
1432
1433 // We have changed the basic block
1434 changed_ = true;
1435 }
1436
1437 // ==== High-level intrinsic expander ==========================================
1438
Expand_FPCompare(llvm::Value * src1_value,llvm::Value * src2_value,bool gt_bias)1439 llvm::Value* GBCExpanderPass::Expand_FPCompare(llvm::Value* src1_value,
1440 llvm::Value* src2_value,
1441 bool gt_bias) {
1442 llvm::Value* cmp_eq = irb_.CreateFCmpOEQ(src1_value, src2_value);
1443 llvm::Value* cmp_lt;
1444
1445 if (gt_bias) {
1446 cmp_lt = irb_.CreateFCmpOLT(src1_value, src2_value);
1447 } else {
1448 cmp_lt = irb_.CreateFCmpULT(src1_value, src2_value);
1449 }
1450
1451 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1452 }
1453
Expand_LongCompare(llvm::Value * src1_value,llvm::Value * src2_value)1454 llvm::Value* GBCExpanderPass::Expand_LongCompare(llvm::Value* src1_value, llvm::Value* src2_value) {
1455 llvm::Value* cmp_eq = irb_.CreateICmpEQ(src1_value, src2_value);
1456 llvm::Value* cmp_lt = irb_.CreateICmpSLT(src1_value, src2_value);
1457
1458 return EmitCompareResultSelection(cmp_eq, cmp_lt);
1459 }
1460
EmitCompareResultSelection(llvm::Value * cmp_eq,llvm::Value * cmp_lt)1461 llvm::Value* GBCExpanderPass::EmitCompareResultSelection(llvm::Value* cmp_eq,
1462 llvm::Value* cmp_lt) {
1463 llvm::Constant* zero = irb_.getJInt(0);
1464 llvm::Constant* pos1 = irb_.getJInt(1);
1465 llvm::Constant* neg1 = irb_.getJInt(-1);
1466
1467 llvm::Value* result_lt = irb_.CreateSelect(cmp_lt, neg1, pos1);
1468 llvm::Value* result_eq = irb_.CreateSelect(cmp_eq, zero, result_lt);
1469
1470 return result_eq;
1471 }
1472
Expand_IntegerShift(llvm::Value * src1_value,llvm::Value * src2_value,IntegerShiftKind kind,JType op_jty)1473 llvm::Value* GBCExpanderPass::Expand_IntegerShift(llvm::Value* src1_value,
1474 llvm::Value* src2_value,
1475 IntegerShiftKind kind,
1476 JType op_jty) {
1477 DCHECK(op_jty == kInt || op_jty == kLong);
1478
1479 // Mask and zero-extend RHS properly
1480 if (op_jty == kInt) {
1481 src2_value = irb_.CreateAnd(src2_value, 0x1f);
1482 } else {
1483 llvm::Value* masked_src2_value = irb_.CreateAnd(src2_value, 0x3f);
1484 src2_value = irb_.CreateZExt(masked_src2_value, irb_.getJLongTy());
1485 }
1486
1487 // Create integer shift llvm instruction
1488 switch (kind) {
1489 case kIntegerSHL:
1490 return irb_.CreateShl(src1_value, src2_value);
1491
1492 case kIntegerSHR:
1493 return irb_.CreateAShr(src1_value, src2_value);
1494
1495 case kIntegerUSHR:
1496 return irb_.CreateLShr(src1_value, src2_value);
1497
1498 default:
1499 LOG(FATAL) << "Unknown integer shift kind: " << kind;
1500 return NULL;
1501 }
1502 }
1503
SignOrZeroExtendCat1Types(llvm::Value * value,JType jty)1504 llvm::Value* GBCExpanderPass::SignOrZeroExtendCat1Types(llvm::Value* value, JType jty) {
1505 switch (jty) {
1506 case kBoolean:
1507 case kChar:
1508 return irb_.CreateZExt(value, irb_.getJType(kInt));
1509 case kByte:
1510 case kShort:
1511 return irb_.CreateSExt(value, irb_.getJType(kInt));
1512 case kVoid:
1513 case kInt:
1514 case kLong:
1515 case kFloat:
1516 case kDouble:
1517 case kObject:
1518 return value; // Nothing to do.
1519 default:
1520 LOG(FATAL) << "Unknown java type: " << jty;
1521 return NULL;
1522 }
1523 }
1524
TruncateCat1Types(llvm::Value * value,JType jty)1525 llvm::Value* GBCExpanderPass::TruncateCat1Types(llvm::Value* value, JType jty) {
1526 switch (jty) {
1527 case kBoolean:
1528 case kChar:
1529 case kByte:
1530 case kShort:
1531 return irb_.CreateTrunc(value, irb_.getJType(jty));
1532 case kVoid:
1533 case kInt:
1534 case kLong:
1535 case kFloat:
1536 case kDouble:
1537 case kObject:
1538 return value; // Nothing to do.
1539 default:
1540 LOG(FATAL) << "Unknown java type: " << jty;
1541 return NULL;
1542 }
1543 }
1544
Expand_HLArrayGet(llvm::CallInst & call_inst,JType elem_jty)1545 llvm::Value* GBCExpanderPass::Expand_HLArrayGet(llvm::CallInst& call_inst,
1546 JType elem_jty) {
1547 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1548 llvm::Value* array_addr = call_inst.getArgOperand(1);
1549 llvm::Value* index_value = call_inst.getArgOperand(2);
1550 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
1551
1552 EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
1553 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value,
1554 opt_flags);
1555
1556 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1557
1558 llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr, kTBAAHeapArray, elem_jty);
1559
1560 return SignOrZeroExtendCat1Types(array_elem_value, elem_jty);
1561 }
1562
1563
Expand_HLArrayPut(llvm::CallInst & call_inst,JType elem_jty)1564 void GBCExpanderPass::Expand_HLArrayPut(llvm::CallInst& call_inst,
1565 JType elem_jty) {
1566 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1567 llvm::Value* new_value = call_inst.getArgOperand(1);
1568 llvm::Value* array_addr = call_inst.getArgOperand(2);
1569 llvm::Value* index_value = call_inst.getArgOperand(3);
1570 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
1571
1572 EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
1573 EmitGuard_ArrayIndexOutOfBoundsException(dex_pc, array_addr, index_value,
1574 opt_flags);
1575
1576 new_value = TruncateCat1Types(new_value, elem_jty);
1577
1578 llvm::Value* array_elem_addr = EmitArrayGEP(array_addr, index_value, elem_jty);
1579
1580 if (elem_jty == kObject) { // If put an object, check the type, and mark GC card table.
1581 llvm::Function* runtime_func = irb_.GetRuntime(CheckPutArrayElement);
1582
1583 irb_.CreateCall2(runtime_func, new_value, array_addr);
1584
1585 EmitGuard_ExceptionLandingPad(dex_pc);
1586
1587 EmitMarkGCCard(new_value, array_addr);
1588 }
1589
1590 irb_.CreateStore(new_value, array_elem_addr, kTBAAHeapArray, elem_jty);
1591
1592 return;
1593 }
1594
Expand_HLIGet(llvm::CallInst & call_inst,JType field_jty)1595 llvm::Value* GBCExpanderPass::Expand_HLIGet(llvm::CallInst& call_inst,
1596 JType field_jty) {
1597 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1598 llvm::Value* object_addr = call_inst.getArgOperand(1);
1599 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(2));
1600 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
1601
1602 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
1603
1604 llvm::Value* field_value;
1605
1606 art::MemberOffset field_offset(0u);
1607 bool is_volatile;
1608 bool is_fast_path = driver_->ComputeInstanceFieldInfo(
1609 field_idx, dex_compilation_unit_, false, &field_offset, &is_volatile);
1610
1611 if (!is_fast_path) {
1612 llvm::Function* runtime_func;
1613
1614 if (field_jty == kObject) {
1615 runtime_func = irb_.GetRuntime(GetObjectInstance);
1616 } else if (field_jty == kLong || field_jty == kDouble) {
1617 runtime_func = irb_.GetRuntime(Get64Instance);
1618 } else {
1619 runtime_func = irb_.GetRuntime(Get32Instance);
1620 }
1621
1622 llvm::ConstantInt* field_idx_value = irb_.getInt32(field_idx);
1623
1624 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1625
1626 EmitUpdateDexPC(dex_pc);
1627
1628 field_value = irb_.CreateCall3(runtime_func, field_idx_value,
1629 method_object_addr, object_addr);
1630
1631 EmitGuard_ExceptionLandingPad(dex_pc);
1632
1633 if (field_jty == kFloat || field_jty == kDouble) {
1634 field_value = irb_.CreateBitCast(field_value, irb_.getJType(field_jty));
1635 }
1636 } else {
1637 DCHECK_GE(field_offset.Int32Value(), 0);
1638
1639 llvm::PointerType* field_type =
1640 irb_.getJType(field_jty)->getPointerTo();
1641
1642 llvm::ConstantInt* field_offset_value = irb_.getPtrEquivInt(field_offset.Int32Value());
1643
1644 llvm::Value* field_addr =
1645 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1646
1647 field_value = irb_.CreateLoad(field_addr, kTBAAHeapInstance, field_jty);
1648 field_value = SignOrZeroExtendCat1Types(field_value, field_jty);
1649
1650 if (is_volatile) {
1651 irb_.CreateMemoryBarrier(art::kLoadAny);
1652 }
1653 }
1654
1655 return field_value;
1656 }
1657
Expand_HLIPut(llvm::CallInst & call_inst,JType field_jty)1658 void GBCExpanderPass::Expand_HLIPut(llvm::CallInst& call_inst,
1659 JType field_jty) {
1660 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1661 llvm::Value* new_value = call_inst.getArgOperand(1);
1662 llvm::Value* object_addr = call_inst.getArgOperand(2);
1663 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(3));
1664 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
1665
1666 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
1667
1668 art::MemberOffset field_offset(0u);
1669 bool is_volatile;
1670 bool is_fast_path = driver_->ComputeInstanceFieldInfo(
1671 field_idx, dex_compilation_unit_, true, &field_offset, &is_volatile);
1672
1673 if (!is_fast_path) {
1674 llvm::Function* runtime_func;
1675
1676 if (field_jty == kFloat) {
1677 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kInt));
1678 } else if (field_jty == kDouble) {
1679 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kLong));
1680 }
1681
1682 if (field_jty == kObject) {
1683 runtime_func = irb_.GetRuntime(SetObjectInstance);
1684 } else if (field_jty == kLong || field_jty == kDouble) {
1685 runtime_func = irb_.GetRuntime(Set64Instance);
1686 } else {
1687 runtime_func = irb_.GetRuntime(Set32Instance);
1688 }
1689
1690 llvm::Value* field_idx_value = irb_.getInt32(field_idx);
1691
1692 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1693
1694 EmitUpdateDexPC(dex_pc);
1695
1696 irb_.CreateCall4(runtime_func, field_idx_value,
1697 method_object_addr, object_addr, new_value);
1698
1699 EmitGuard_ExceptionLandingPad(dex_pc);
1700
1701 } else {
1702 DCHECK_GE(field_offset.Int32Value(), 0);
1703
1704 if (is_volatile) {
1705 irb_.CreateMemoryBarrier(art::kAnyStore);
1706 }
1707
1708 llvm::PointerType* field_type =
1709 irb_.getJType(field_jty)->getPointerTo();
1710
1711 llvm::Value* field_offset_value = irb_.getPtrEquivInt(field_offset.Int32Value());
1712
1713 llvm::Value* field_addr =
1714 irb_.CreatePtrDisp(object_addr, field_offset_value, field_type);
1715
1716 new_value = TruncateCat1Types(new_value, field_jty);
1717 irb_.CreateStore(new_value, field_addr, kTBAAHeapInstance, field_jty);
1718
1719 if (is_volatile) {
1720 irb_.CreateMemoryBarrier(art::kAnyAny);
1721 }
1722
1723 if (field_jty == kObject) { // If put an object, mark the GC card table.
1724 EmitMarkGCCard(new_value, object_addr);
1725 }
1726 }
1727
1728 return;
1729 }
1730
EmitLoadConstantClass(uint32_t dex_pc,uint32_t type_idx)1731 llvm::Value* GBCExpanderPass::EmitLoadConstantClass(uint32_t dex_pc,
1732 uint32_t type_idx) {
1733 if (!driver_->CanAccessTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
1734 *dex_compilation_unit_->GetDexFile(), type_idx)) {
1735 llvm::Value* type_idx_value = irb_.getInt32(type_idx);
1736
1737 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1738
1739 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1740
1741 llvm::Function* runtime_func = irb_.GetRuntime(InitializeTypeAndVerifyAccess);
1742
1743 EmitUpdateDexPC(dex_pc);
1744
1745 llvm::Value* type_object_addr =
1746 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1747
1748 EmitGuard_ExceptionLandingPad(dex_pc);
1749
1750 return type_object_addr;
1751
1752 } else {
1753 // Try to load the class (type) object from the test cache.
1754 llvm::Value* type_field_addr =
1755 EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
1756
1757 llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
1758
1759 if (driver_->CanAssumeTypeIsPresentInDexCache(*dex_compilation_unit_->GetDexFile(), type_idx)) {
1760 return type_object_addr;
1761 }
1762
1763 llvm::BasicBlock* block_original = irb_.GetInsertBlock();
1764
1765 // Test whether class (type) object is in the dex cache or not
1766 llvm::Value* equal_null =
1767 irb_.CreateICmpEQ(type_object_addr, irb_.getJNull());
1768
1769 llvm::BasicBlock* block_cont =
1770 CreateBasicBlockWithDexPC(dex_pc, "cont");
1771
1772 llvm::BasicBlock* block_load_class =
1773 CreateBasicBlockWithDexPC(dex_pc, "load_class");
1774
1775 irb_.CreateCondBr(equal_null, block_load_class, block_cont, kUnlikely);
1776
1777 // Failback routine to load the class object
1778 irb_.SetInsertPoint(block_load_class);
1779
1780 llvm::Function* runtime_func = irb_.GetRuntime(InitializeType);
1781
1782 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1783
1784 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1785
1786 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1787
1788 EmitUpdateDexPC(dex_pc);
1789
1790 llvm::Value* loaded_type_object_addr =
1791 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1792
1793 EmitGuard_ExceptionLandingPad(dex_pc);
1794
1795 llvm::BasicBlock* block_after_load_class = irb_.GetInsertBlock();
1796
1797 irb_.CreateBr(block_cont);
1798
1799 // Now the class object must be loaded
1800 irb_.SetInsertPoint(block_cont);
1801
1802 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1803
1804 phi->addIncoming(type_object_addr, block_original);
1805 phi->addIncoming(loaded_type_object_addr, block_after_load_class);
1806
1807 return phi;
1808 }
1809 }
1810
EmitLoadStaticStorage(uint32_t dex_pc,uint32_t type_idx)1811 llvm::Value* GBCExpanderPass::EmitLoadStaticStorage(uint32_t dex_pc,
1812 uint32_t type_idx) {
1813 llvm::BasicBlock* block_load_static =
1814 CreateBasicBlockWithDexPC(dex_pc, "load_static");
1815
1816 llvm::BasicBlock* block_check_init = CreateBasicBlockWithDexPC(dex_pc, "init");
1817 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
1818
1819 // Load static storage from dex cache
1820 llvm::Value* storage_field_addr = EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
1821
1822 llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
1823
1824 // Test: Is the class resolved?
1825 llvm::Value* equal_null = irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
1826
1827 irb_.CreateCondBr(equal_null, block_load_static, block_check_init, kUnlikely);
1828
1829 // storage_object_addr != null, so check if its initialized.
1830 irb_.SetInsertPoint(block_check_init);
1831
1832 llvm::Value* class_status =
1833 irb_.LoadFromObjectOffset(storage_object_addr,
1834 art::mirror::Class::StatusOffset().Int32Value(),
1835 irb_.getJIntTy(), kTBAAHeapInstance);
1836
1837 llvm::Value* is_not_initialized =
1838 irb_.CreateICmpULT(class_status, irb_.getInt32(art::mirror::Class::kStatusInitialized));
1839
1840 irb_.CreateCondBr(is_not_initialized, block_load_static, block_cont, kUnlikely);
1841
1842 // Failback routine to load the class object
1843 irb_.SetInsertPoint(block_load_static);
1844
1845 llvm::Function* runtime_func = irb_.GetRuntime(InitializeStaticStorage);
1846
1847 llvm::Constant* type_idx_value = irb_.getInt32(type_idx);
1848
1849 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1850
1851 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
1852
1853 EmitUpdateDexPC(dex_pc);
1854
1855 llvm::Value* loaded_storage_object_addr =
1856 irb_.CreateCall3(runtime_func, type_idx_value, method_object_addr, thread_object_addr);
1857
1858 EmitGuard_ExceptionLandingPad(dex_pc);
1859
1860 llvm::BasicBlock* block_after_load_static = irb_.GetInsertBlock();
1861
1862 irb_.CreateBr(block_cont);
1863
1864 // Now the class object must be loaded
1865 irb_.SetInsertPoint(block_cont);
1866
1867 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
1868
1869 phi->addIncoming(storage_object_addr, block_check_init);
1870 phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
1871
1872 // Ensure load of status and load of value don't re-order.
1873 irb_.CreateMemoryBarrier(art::kLoadAny);
1874
1875 return phi;
1876 }
1877
Expand_HLSget(llvm::CallInst & call_inst,JType field_jty)1878 llvm::Value* GBCExpanderPass::Expand_HLSget(llvm::CallInst& call_inst,
1879 JType field_jty) {
1880 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1881 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1882
1883 art::MemberOffset field_offset(0u);
1884 uint32_t ssb_index;
1885 bool is_referrers_class;
1886 bool is_volatile;
1887 bool is_initialized;
1888
1889 bool is_fast_path = driver_->ComputeStaticFieldInfo(
1890 field_idx, dex_compilation_unit_, false,
1891 &field_offset, &ssb_index, &is_referrers_class, &is_volatile, &is_initialized);
1892
1893 llvm::Value* static_field_value;
1894
1895 if (!is_fast_path) {
1896 llvm::Function* runtime_func;
1897
1898 if (field_jty == kObject) {
1899 runtime_func = irb_.GetRuntime(GetObjectStatic);
1900 } else if (field_jty == kLong || field_jty == kDouble) {
1901 runtime_func = irb_.GetRuntime(Get64Static);
1902 } else {
1903 runtime_func = irb_.GetRuntime(Get32Static);
1904 }
1905
1906 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1907
1908 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1909
1910 EmitUpdateDexPC(dex_pc);
1911
1912 static_field_value =
1913 irb_.CreateCall2(runtime_func, field_idx_value, method_object_addr);
1914
1915 EmitGuard_ExceptionLandingPad(dex_pc);
1916
1917 if (field_jty == kFloat || field_jty == kDouble) {
1918 static_field_value = irb_.CreateBitCast(static_field_value, irb_.getJType(field_jty));
1919 }
1920 } else {
1921 DCHECK_GE(field_offset.Int32Value(), 0);
1922
1923 llvm::Value* static_storage_addr = NULL;
1924
1925 if (is_referrers_class) {
1926 // Fast path, static storage base is this method's class
1927 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1928
1929 static_storage_addr =
1930 irb_.LoadFromObjectOffset(method_object_addr,
1931 art::mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
1932 irb_.getJObjectTy(),
1933 kTBAAConstJObject);
1934 } else {
1935 // Medium path, static storage base in a different class which
1936 // requires checks that the other class is initialized
1937 DCHECK_NE(ssb_index, art::DexFile::kDexNoIndex);
1938 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
1939 }
1940
1941 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset.Int32Value());
1942
1943 llvm::Value* static_field_addr =
1944 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
1945 irb_.getJType(field_jty)->getPointerTo());
1946
1947 static_field_value = irb_.CreateLoad(static_field_addr, kTBAAHeapStatic, field_jty);
1948 static_field_value = SignOrZeroExtendCat1Types(static_field_value, field_jty);
1949
1950 if (is_volatile) {
1951 irb_.CreateMemoryBarrier(art::kLoadAny);
1952 }
1953 }
1954
1955 return static_field_value;
1956 }
1957
Expand_HLSput(llvm::CallInst & call_inst,JType field_jty)1958 void GBCExpanderPass::Expand_HLSput(llvm::CallInst& call_inst,
1959 JType field_jty) {
1960 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
1961 uint32_t field_idx = LV2UInt(call_inst.getArgOperand(0));
1962 llvm::Value* new_value = call_inst.getArgOperand(1);
1963
1964 if (field_jty == kFloat || field_jty == kDouble) {
1965 new_value = irb_.CreateBitCast(new_value, irb_.getJType(field_jty));
1966 }
1967
1968 art::MemberOffset field_offset(0u);
1969 uint32_t ssb_index;
1970 bool is_referrers_class;
1971 bool is_volatile;
1972 bool is_initialized;
1973
1974 bool is_fast_path = driver_->ComputeStaticFieldInfo(
1975 field_idx, dex_compilation_unit_, true,
1976 &field_offset, &ssb_index, &is_referrers_class, &is_volatile, &is_initialized);
1977
1978 if (!is_fast_path) {
1979 llvm::Function* runtime_func;
1980
1981 if (field_jty == kObject) {
1982 runtime_func = irb_.GetRuntime(SetObjectStatic);
1983 } else if (field_jty == kLong || field_jty == kDouble) {
1984 runtime_func = irb_.GetRuntime(Set64Static);
1985 } else {
1986 runtime_func = irb_.GetRuntime(Set32Static);
1987 }
1988
1989 if (field_jty == kFloat) {
1990 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kInt));
1991 } else if (field_jty == kDouble) {
1992 new_value = irb_.CreateBitCast(new_value, irb_.getJType(kLong));
1993 }
1994
1995 llvm::Constant* field_idx_value = irb_.getInt32(field_idx);
1996
1997 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
1998
1999 EmitUpdateDexPC(dex_pc);
2000
2001 irb_.CreateCall3(runtime_func, field_idx_value,
2002 method_object_addr, new_value);
2003
2004 EmitGuard_ExceptionLandingPad(dex_pc);
2005
2006 } else {
2007 DCHECK_GE(field_offset.Int32Value(), 0);
2008
2009 llvm::Value* static_storage_addr = NULL;
2010
2011 if (is_referrers_class) {
2012 // Fast path, static storage base is this method's class
2013 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2014
2015 static_storage_addr =
2016 irb_.LoadFromObjectOffset(method_object_addr,
2017 art::mirror::ArtMethod::DeclaringClassOffset().Int32Value(),
2018 irb_.getJObjectTy(),
2019 kTBAAConstJObject);
2020 } else {
2021 // Medium path, static storage base in a different class which
2022 // requires checks that the other class is initialized
2023 DCHECK_NE(ssb_index, art::DexFile::kDexNoIndex);
2024 static_storage_addr = EmitLoadStaticStorage(dex_pc, ssb_index);
2025 }
2026
2027 if (is_volatile) {
2028 irb_.CreateMemoryBarrier(art::kAnyStore);
2029 }
2030
2031 llvm::Value* static_field_offset_value = irb_.getPtrEquivInt(field_offset.Int32Value());
2032
2033 llvm::Value* static_field_addr =
2034 irb_.CreatePtrDisp(static_storage_addr, static_field_offset_value,
2035 irb_.getJType(field_jty)->getPointerTo());
2036
2037 new_value = TruncateCat1Types(new_value, field_jty);
2038 irb_.CreateStore(new_value, static_field_addr, kTBAAHeapStatic, field_jty);
2039
2040 if (is_volatile) {
2041 irb_.CreateMemoryBarrier(art::kAnyAny);
2042 }
2043
2044 if (field_jty == kObject) { // If put an object, mark the GC card table.
2045 EmitMarkGCCard(new_value, static_storage_addr);
2046 }
2047 }
2048
2049 return;
2050 }
2051
Expand_ConstString(llvm::CallInst & call_inst)2052 llvm::Value* GBCExpanderPass::Expand_ConstString(llvm::CallInst& call_inst) {
2053 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2054 uint32_t string_idx = LV2UInt(call_inst.getArgOperand(0));
2055
2056 llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
2057
2058 llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
2059
2060 if (!driver_->CanAssumeStringIsPresentInDexCache(*dex_compilation_unit_->GetDexFile(),
2061 string_idx)) {
2062 llvm::BasicBlock* block_str_exist =
2063 CreateBasicBlockWithDexPC(dex_pc, "str_exist");
2064
2065 llvm::BasicBlock* block_str_resolve =
2066 CreateBasicBlockWithDexPC(dex_pc, "str_resolve");
2067
2068 llvm::BasicBlock* block_cont =
2069 CreateBasicBlockWithDexPC(dex_pc, "str_cont");
2070
2071 // Test: Is the string resolved and in the dex cache?
2072 llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.getJNull());
2073
2074 irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist, kUnlikely);
2075
2076 // String is resolved, go to next basic block.
2077 irb_.SetInsertPoint(block_str_exist);
2078 irb_.CreateBr(block_cont);
2079
2080 // String is not resolved yet, resolve it now.
2081 irb_.SetInsertPoint(block_str_resolve);
2082
2083 llvm::Function* runtime_func = irb_.GetRuntime(ResolveString);
2084
2085 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2086
2087 llvm::Value* string_idx_value = irb_.getInt32(string_idx);
2088
2089 EmitUpdateDexPC(dex_pc);
2090
2091 llvm::Value* result = irb_.CreateCall2(runtime_func, method_object_addr,
2092 string_idx_value);
2093
2094 EmitGuard_ExceptionLandingPad(dex_pc);
2095
2096 irb_.CreateBr(block_cont);
2097
2098
2099 llvm::BasicBlock* block_pre_cont = irb_.GetInsertBlock();
2100
2101 irb_.SetInsertPoint(block_cont);
2102
2103 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
2104
2105 phi->addIncoming(string_addr, block_str_exist);
2106 phi->addIncoming(result, block_pre_cont);
2107
2108 string_addr = phi;
2109 }
2110
2111 return string_addr;
2112 }
2113
Expand_ConstClass(llvm::CallInst & call_inst)2114 llvm::Value* GBCExpanderPass::Expand_ConstClass(llvm::CallInst& call_inst) {
2115 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2116 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2117
2118 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
2119
2120 return type_object_addr;
2121 }
2122
Expand_MonitorEnter(llvm::CallInst & call_inst)2123 void GBCExpanderPass::Expand_MonitorEnter(llvm::CallInst& call_inst) {
2124 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2125 llvm::Value* object_addr = call_inst.getArgOperand(1);
2126 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
2127
2128 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
2129
2130 EmitUpdateDexPC(dex_pc);
2131
2132 irb_.Runtime().EmitLockObject(object_addr);
2133
2134 return;
2135 }
2136
Expand_MonitorExit(llvm::CallInst & call_inst)2137 void GBCExpanderPass::Expand_MonitorExit(llvm::CallInst& call_inst) {
2138 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2139 llvm::Value* object_addr = call_inst.getArgOperand(1);
2140 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
2141
2142 EmitGuard_NullPointerException(dex_pc, object_addr, opt_flags);
2143
2144 EmitUpdateDexPC(dex_pc);
2145
2146 irb_.Runtime().EmitUnlockObject(object_addr);
2147
2148 EmitGuard_ExceptionLandingPad(dex_pc);
2149
2150 return;
2151 }
2152
Expand_HLCheckCast(llvm::CallInst & call_inst)2153 void GBCExpanderPass::Expand_HLCheckCast(llvm::CallInst& call_inst) {
2154 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2155 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2156 llvm::Value* object_addr = call_inst.getArgOperand(1);
2157
2158 llvm::BasicBlock* block_test_class =
2159 CreateBasicBlockWithDexPC(dex_pc, "test_class");
2160
2161 llvm::BasicBlock* block_test_sub_class =
2162 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
2163
2164 llvm::BasicBlock* block_cont =
2165 CreateBasicBlockWithDexPC(dex_pc, "checkcast_cont");
2166
2167 // Test: Is the reference equal to null? Act as no-op when it is null.
2168 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
2169
2170 irb_.CreateCondBr(equal_null, block_cont, block_test_class, kUnlikely);
2171
2172 // Test: Is the object instantiated from the given class?
2173 irb_.SetInsertPoint(block_test_class);
2174 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
2175 DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
2176
2177 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
2178
2179 llvm::Value* object_type_field_addr =
2180 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
2181
2182 llvm::Value* object_type_object_addr =
2183 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
2184
2185 llvm::Value* equal_class =
2186 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
2187
2188 irb_.CreateCondBr(equal_class, block_cont, block_test_sub_class, kLikely);
2189
2190 // Test: Is the object instantiated from the subclass of the given class?
2191 irb_.SetInsertPoint(block_test_sub_class);
2192
2193 EmitUpdateDexPC(dex_pc);
2194
2195 irb_.CreateCall2(irb_.GetRuntime(CheckCast),
2196 type_object_addr, object_type_object_addr);
2197
2198 EmitGuard_ExceptionLandingPad(dex_pc);
2199
2200 irb_.CreateBr(block_cont);
2201
2202 irb_.SetInsertPoint(block_cont);
2203
2204 return;
2205 }
2206
Expand_InstanceOf(llvm::CallInst & call_inst)2207 llvm::Value* GBCExpanderPass::Expand_InstanceOf(llvm::CallInst& call_inst) {
2208 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2209 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2210 llvm::Value* object_addr = call_inst.getArgOperand(1);
2211
2212 llvm::BasicBlock* block_nullp =
2213 CreateBasicBlockWithDexPC(dex_pc, "nullp");
2214
2215 llvm::BasicBlock* block_test_class =
2216 CreateBasicBlockWithDexPC(dex_pc, "test_class");
2217
2218 llvm::BasicBlock* block_class_equals =
2219 CreateBasicBlockWithDexPC(dex_pc, "class_eq");
2220
2221 llvm::BasicBlock* block_test_sub_class =
2222 CreateBasicBlockWithDexPC(dex_pc, "test_sub_class");
2223
2224 llvm::BasicBlock* block_cont =
2225 CreateBasicBlockWithDexPC(dex_pc, "instance_of_cont");
2226
2227 // Overview of the following code :
2228 // We check for null, if so, then false, otherwise check for class == . If so
2229 // then true, otherwise do callout slowpath.
2230 //
2231 // Test: Is the reference equal to null? Set 0 when it is null.
2232 llvm::Value* equal_null = irb_.CreateICmpEQ(object_addr, irb_.getJNull());
2233
2234 irb_.CreateCondBr(equal_null, block_nullp, block_test_class, kUnlikely);
2235
2236 irb_.SetInsertPoint(block_nullp);
2237 irb_.CreateBr(block_cont);
2238
2239 // Test: Is the object instantiated from the given class?
2240 irb_.SetInsertPoint(block_test_class);
2241 llvm::Value* type_object_addr = EmitLoadConstantClass(dex_pc, type_idx);
2242 DCHECK_EQ(art::mirror::Object::ClassOffset().Int32Value(), 0);
2243
2244 llvm::PointerType* jobject_ptr_ty = irb_.getJObjectTy();
2245
2246 llvm::Value* object_type_field_addr =
2247 irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
2248
2249 llvm::Value* object_type_object_addr =
2250 irb_.CreateLoad(object_type_field_addr, kTBAAConstJObject);
2251
2252 llvm::Value* equal_class =
2253 irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
2254
2255 irb_.CreateCondBr(equal_class, block_class_equals, block_test_sub_class, kLikely);
2256
2257 irb_.SetInsertPoint(block_class_equals);
2258 irb_.CreateBr(block_cont);
2259
2260 // Test: Is the object instantiated from the subclass of the given class?
2261 irb_.SetInsertPoint(block_test_sub_class);
2262 llvm::Value* result =
2263 irb_.CreateCall2(irb_.GetRuntime(IsAssignable),
2264 type_object_addr, object_type_object_addr);
2265 irb_.CreateBr(block_cont);
2266
2267 irb_.SetInsertPoint(block_cont);
2268
2269 llvm::PHINode* phi = irb_.CreatePHI(irb_.getJIntTy(), 3);
2270
2271 phi->addIncoming(irb_.getJInt(0), block_nullp);
2272 phi->addIncoming(irb_.getJInt(1), block_class_equals);
2273 phi->addIncoming(result, block_test_sub_class);
2274
2275 return phi;
2276 }
2277
Expand_NewInstance(llvm::CallInst & call_inst)2278 llvm::Value* GBCExpanderPass::Expand_NewInstance(llvm::CallInst& call_inst) {
2279 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2280 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2281
2282 llvm::Function* runtime_func;
2283 if (driver_->CanAccessInstantiableTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
2284 *dex_compilation_unit_->GetDexFile(),
2285 type_idx)) {
2286 runtime_func = irb_.GetRuntime(AllocObject);
2287 } else {
2288 runtime_func = irb_.GetRuntime(AllocObjectWithAccessCheck);
2289 }
2290
2291 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2292
2293 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2294
2295 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2296
2297 EmitUpdateDexPC(dex_pc);
2298
2299 llvm::Value* object_addr =
2300 irb_.CreateCall3(runtime_func, type_index_value, method_object_addr, thread_object_addr);
2301
2302 EmitGuard_ExceptionLandingPad(dex_pc);
2303
2304 return object_addr;
2305 }
2306
Expand_HLInvoke(llvm::CallInst & call_inst)2307 llvm::Value* GBCExpanderPass::Expand_HLInvoke(llvm::CallInst& call_inst) {
2308 art::InvokeType invoke_type = static_cast<art::InvokeType>(LV2UInt(call_inst.getArgOperand(0)));
2309 bool is_static = (invoke_type == art::kStatic);
2310
2311 if (!is_static) {
2312 // Test: Is *this* parameter equal to null?
2313 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2314 llvm::Value* this_addr = call_inst.getArgOperand(3);
2315 int opt_flags = LV2UInt(call_inst.getArgOperand(2));
2316
2317 EmitGuard_NullPointerException(dex_pc, this_addr, opt_flags);
2318 }
2319
2320 llvm::Value* result = NULL;
2321 if (EmitIntrinsic(call_inst, &result)) {
2322 return result;
2323 }
2324
2325 return EmitInvoke(call_inst);
2326 }
2327
Expand_OptArrayLength(llvm::CallInst & call_inst)2328 llvm::Value* GBCExpanderPass::Expand_OptArrayLength(llvm::CallInst& call_inst) {
2329 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2330 // Get the array object address
2331 llvm::Value* array_addr = call_inst.getArgOperand(1);
2332 int opt_flags = LV2UInt(call_inst.getArgOperand(0));
2333
2334 EmitGuard_NullPointerException(dex_pc, array_addr, opt_flags);
2335
2336 // Get the array length and store it to the register
2337 return EmitLoadArrayLength(array_addr);
2338 }
2339
Expand_NewArray(llvm::CallInst & call_inst)2340 llvm::Value* GBCExpanderPass::Expand_NewArray(llvm::CallInst& call_inst) {
2341 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2342 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(0));
2343 llvm::Value* length = call_inst.getArgOperand(1);
2344
2345 return EmitAllocNewArray(dex_pc, length, type_idx, false);
2346 }
2347
Expand_HLFilledNewArray(llvm::CallInst & call_inst)2348 llvm::Value* GBCExpanderPass::Expand_HLFilledNewArray(llvm::CallInst& call_inst) {
2349 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2350 uint32_t type_idx = LV2UInt(call_inst.getArgOperand(1));
2351 uint32_t length = call_inst.getNumArgOperands() - 3;
2352
2353 llvm::Value* object_addr =
2354 EmitAllocNewArray(dex_pc, irb_.getInt32(length), type_idx, true);
2355
2356 if (length > 0) {
2357 // Check for the element type
2358 uint32_t type_desc_len = 0;
2359 const char* type_desc =
2360 dex_compilation_unit_->GetDexFile()->StringByTypeIdx(type_idx, &type_desc_len);
2361
2362 DCHECK_GE(type_desc_len, 2u); // should be guaranteed by verifier
2363 DCHECK_EQ(type_desc[0], '['); // should be guaranteed by verifier
2364 bool is_elem_int_ty = (type_desc[1] == 'I');
2365
2366 uint32_t alignment;
2367 llvm::Constant* elem_size;
2368 llvm::PointerType* field_type;
2369
2370 // NOTE: Currently filled-new-array only supports 'L', '[', and 'I'
2371 // as the element, thus we are only checking 2 cases: primitive int and
2372 // non-primitive type.
2373 if (is_elem_int_ty) {
2374 alignment = sizeof(int32_t);
2375 elem_size = irb_.getPtrEquivInt(sizeof(int32_t));
2376 field_type = irb_.getJIntTy()->getPointerTo();
2377 } else {
2378 alignment = irb_.getSizeOfPtrEquivInt();
2379 elem_size = irb_.getSizeOfPtrEquivIntValue();
2380 field_type = irb_.getJObjectTy()->getPointerTo();
2381 }
2382
2383 llvm::Value* data_field_offset =
2384 irb_.getPtrEquivInt(art::mirror::Array::DataOffset(alignment).Int32Value());
2385
2386 llvm::Value* data_field_addr =
2387 irb_.CreatePtrDisp(object_addr, data_field_offset, field_type);
2388
2389 // TODO: Tune this code. Currently we are generating one instruction for
2390 // one element which may be very space consuming. Maybe changing to use
2391 // memcpy may help; however, since we can't guarantee that the alloca of
2392 // dalvik register are continuous, we can't perform such optimization yet.
2393 for (uint32_t i = 0; i < length; ++i) {
2394 llvm::Value* reg_value = call_inst.getArgOperand(i+3);
2395
2396 irb_.CreateStore(reg_value, data_field_addr, kTBAAHeapArray);
2397
2398 data_field_addr =
2399 irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
2400 }
2401 }
2402
2403 return object_addr;
2404 }
2405
Expand_HLFillArrayData(llvm::CallInst & call_inst)2406 void GBCExpanderPass::Expand_HLFillArrayData(llvm::CallInst& call_inst) {
2407 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2408 int32_t payload_offset = static_cast<int32_t>(dex_pc) +
2409 LV2SInt(call_inst.getArgOperand(0));
2410 llvm::Value* array_addr = call_inst.getArgOperand(1);
2411
2412 const art::Instruction::ArrayDataPayload* payload =
2413 reinterpret_cast<const art::Instruction::ArrayDataPayload*>(
2414 dex_compilation_unit_->GetCodeItem()->insns_ + payload_offset);
2415
2416 if (payload->element_count == 0) {
2417 // When the number of the elements in the payload is zero, we don't have
2418 // to copy any numbers. However, we should check whether the array object
2419 // address is equal to null or not.
2420 EmitGuard_NullPointerException(dex_pc, array_addr, 0);
2421 } else {
2422 // To save the code size, we are going to call the runtime function to
2423 // copy the content from DexFile.
2424
2425 // NOTE: We will check for the NullPointerException in the runtime.
2426
2427 llvm::Function* runtime_func = irb_.GetRuntime(FillArrayData);
2428
2429 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2430
2431 EmitUpdateDexPC(dex_pc);
2432
2433 irb_.CreateCall4(runtime_func,
2434 method_object_addr, irb_.getInt32(dex_pc),
2435 array_addr, irb_.getInt32(payload_offset));
2436
2437 EmitGuard_ExceptionLandingPad(dex_pc);
2438 }
2439
2440 return;
2441 }
2442
EmitAllocNewArray(uint32_t dex_pc,llvm::Value * array_length_value,uint32_t type_idx,bool is_filled_new_array)2443 llvm::Value* GBCExpanderPass::EmitAllocNewArray(uint32_t dex_pc,
2444 llvm::Value* array_length_value,
2445 uint32_t type_idx,
2446 bool is_filled_new_array) {
2447 llvm::Function* runtime_func;
2448
2449 bool skip_access_check =
2450 driver_->CanAccessTypeWithoutChecks(dex_compilation_unit_->GetDexMethodIndex(),
2451 *dex_compilation_unit_->GetDexFile(), type_idx);
2452
2453
2454 if (is_filled_new_array) {
2455 runtime_func = skip_access_check ?
2456 irb_.GetRuntime(CheckAndAllocArray) :
2457 irb_.GetRuntime(CheckAndAllocArrayWithAccessCheck);
2458 } else {
2459 runtime_func = skip_access_check ?
2460 irb_.GetRuntime(AllocArray) :
2461 irb_.GetRuntime(AllocArrayWithAccessCheck);
2462 }
2463
2464 llvm::Constant* type_index_value = irb_.getInt32(type_idx);
2465
2466 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2467
2468 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2469
2470 EmitUpdateDexPC(dex_pc);
2471
2472 llvm::Value* object_addr =
2473 irb_.CreateCall4(runtime_func, type_index_value, method_object_addr,
2474 array_length_value, thread_object_addr);
2475
2476 EmitGuard_ExceptionLandingPad(dex_pc);
2477
2478 return object_addr;
2479 }
2480
2481 llvm::Value* GBCExpanderPass::
EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,art::InvokeType invoke_type,llvm::Value * this_addr,uint32_t dex_pc,bool is_fast_path)2482 EmitCallRuntimeForCalleeMethodObjectAddr(uint32_t callee_method_idx,
2483 art::InvokeType invoke_type,
2484 llvm::Value* this_addr,
2485 uint32_t dex_pc,
2486 bool is_fast_path) {
2487 llvm::Function* runtime_func = NULL;
2488
2489 switch (invoke_type) {
2490 case art::kStatic:
2491 runtime_func = irb_.GetRuntime(FindStaticMethodWithAccessCheck);
2492 break;
2493
2494 case art::kDirect:
2495 runtime_func = irb_.GetRuntime(FindDirectMethodWithAccessCheck);
2496 break;
2497
2498 case art::kVirtual:
2499 runtime_func = irb_.GetRuntime(FindVirtualMethodWithAccessCheck);
2500 break;
2501
2502 case art::kSuper:
2503 runtime_func = irb_.GetRuntime(FindSuperMethodWithAccessCheck);
2504 break;
2505
2506 case art::kInterface:
2507 if (is_fast_path) {
2508 runtime_func = irb_.GetRuntime(FindInterfaceMethod);
2509 } else {
2510 runtime_func = irb_.GetRuntime(FindInterfaceMethodWithAccessCheck);
2511 }
2512 break;
2513 }
2514
2515 llvm::Value* callee_method_idx_value = irb_.getInt32(callee_method_idx);
2516
2517 if (this_addr == NULL) {
2518 DCHECK_EQ(invoke_type, art::kStatic);
2519 this_addr = irb_.getJNull();
2520 }
2521
2522 llvm::Value* caller_method_object_addr = EmitLoadMethodObjectAddr();
2523
2524 llvm::Value* thread_object_addr = irb_.Runtime().EmitGetCurrentThread();
2525
2526 EmitUpdateDexPC(dex_pc);
2527
2528 llvm::Value* callee_method_object_addr =
2529 irb_.CreateCall4(runtime_func,
2530 callee_method_idx_value,
2531 this_addr,
2532 caller_method_object_addr,
2533 thread_object_addr);
2534
2535 EmitGuard_ExceptionLandingPad(dex_pc);
2536
2537 return callee_method_object_addr;
2538 }
2539
EmitMarkGCCard(llvm::Value * value,llvm::Value * target_addr)2540 void GBCExpanderPass::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
2541 // Using runtime support, let the target can override by InlineAssembly.
2542 irb_.Runtime().EmitMarkGCCard(value, target_addr);
2543 }
2544
EmitUpdateDexPC(uint32_t dex_pc)2545 void GBCExpanderPass::EmitUpdateDexPC(uint32_t dex_pc) {
2546 if (shadow_frame_ == NULL) {
2547 return;
2548 }
2549 irb_.StoreToObjectOffset(shadow_frame_,
2550 art::ShadowFrame::DexPCOffset(),
2551 irb_.getInt32(dex_pc),
2552 kTBAAShadowFrame);
2553 }
2554
EmitGuard_DivZeroException(uint32_t dex_pc,llvm::Value * denominator,JType op_jty)2555 void GBCExpanderPass::EmitGuard_DivZeroException(uint32_t dex_pc,
2556 llvm::Value* denominator,
2557 JType op_jty) {
2558 DCHECK(op_jty == kInt || op_jty == kLong) << op_jty;
2559
2560 llvm::Constant* zero = irb_.getJZero(op_jty);
2561
2562 llvm::Value* equal_zero = irb_.CreateICmpEQ(denominator, zero);
2563
2564 llvm::BasicBlock* block_exception = CreateBasicBlockWithDexPC(dex_pc, "div0");
2565
2566 llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
2567
2568 irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
2569
2570 irb_.SetInsertPoint(block_exception);
2571 EmitUpdateDexPC(dex_pc);
2572 irb_.CreateCall(irb_.GetRuntime(ThrowDivZeroException));
2573 EmitBranchExceptionLandingPad(dex_pc);
2574
2575 irb_.SetInsertPoint(block_continue);
2576 }
2577
EmitGuard_NullPointerException(uint32_t dex_pc,llvm::Value * object,int opt_flags)2578 void GBCExpanderPass::EmitGuard_NullPointerException(uint32_t dex_pc,
2579 llvm::Value* object,
2580 int opt_flags) {
2581 bool ignore_null_check = ((opt_flags & MIR_IGNORE_NULL_CHECK) != 0);
2582 if (ignore_null_check) {
2583 llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc);
2584 if (lpad) {
2585 // There is at least one catch: create a "fake" conditional branch to
2586 // keep the exception edge to the catch block.
2587 landing_pad_phi_mapping_[lpad].push_back(
2588 std::make_pair(current_bb_->getUniquePredecessor(),
2589 irb_.GetInsertBlock()));
2590
2591 llvm::BasicBlock* block_continue =
2592 CreateBasicBlockWithDexPC(dex_pc, "cont");
2593
2594 irb_.CreateCondBr(irb_.getFalse(), lpad, block_continue, kUnlikely);
2595
2596 irb_.SetInsertPoint(block_continue);
2597 }
2598 } else {
2599 llvm::Value* equal_null = irb_.CreateICmpEQ(object, irb_.getJNull());
2600
2601 llvm::BasicBlock* block_exception =
2602 CreateBasicBlockWithDexPC(dex_pc, "nullp");
2603
2604 llvm::BasicBlock* block_continue =
2605 CreateBasicBlockWithDexPC(dex_pc, "cont");
2606
2607 irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
2608
2609 irb_.SetInsertPoint(block_exception);
2610 EmitUpdateDexPC(dex_pc);
2611 irb_.CreateCall(irb_.GetRuntime(ThrowNullPointerException),
2612 irb_.getInt32(dex_pc));
2613 EmitBranchExceptionLandingPad(dex_pc);
2614
2615 irb_.SetInsertPoint(block_continue);
2616 }
2617 }
2618
2619 void
EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,llvm::Value * array,llvm::Value * index,int opt_flags)2620 GBCExpanderPass::EmitGuard_ArrayIndexOutOfBoundsException(uint32_t dex_pc,
2621 llvm::Value* array,
2622 llvm::Value* index,
2623 int opt_flags) {
2624 bool ignore_range_check = ((opt_flags & MIR_IGNORE_RANGE_CHECK) != 0);
2625 if (ignore_range_check) {
2626 llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc);
2627 if (lpad) {
2628 // There is at least one catch: create a "fake" conditional branch to
2629 // keep the exception edge to the catch block.
2630 landing_pad_phi_mapping_[lpad].push_back(
2631 std::make_pair(current_bb_->getUniquePredecessor(),
2632 irb_.GetInsertBlock()));
2633
2634 llvm::BasicBlock* block_continue =
2635 CreateBasicBlockWithDexPC(dex_pc, "cont");
2636
2637 irb_.CreateCondBr(irb_.getFalse(), lpad, block_continue, kUnlikely);
2638
2639 irb_.SetInsertPoint(block_continue);
2640 }
2641 } else {
2642 llvm::Value* array_len = EmitLoadArrayLength(array);
2643
2644 llvm::Value* cmp = irb_.CreateICmpUGE(index, array_len);
2645
2646 llvm::BasicBlock* block_exception =
2647 CreateBasicBlockWithDexPC(dex_pc, "overflow");
2648
2649 llvm::BasicBlock* block_continue =
2650 CreateBasicBlockWithDexPC(dex_pc, "cont");
2651
2652 irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
2653
2654 irb_.SetInsertPoint(block_exception);
2655
2656 EmitUpdateDexPC(dex_pc);
2657 irb_.CreateCall2(irb_.GetRuntime(ThrowIndexOutOfBounds), index, array_len);
2658 EmitBranchExceptionLandingPad(dex_pc);
2659
2660 irb_.SetInsertPoint(block_continue);
2661 }
2662 }
2663
GetFunctionType(llvm::Type * ret_type,uint32_t method_idx,bool is_static)2664 llvm::FunctionType* GBCExpanderPass::GetFunctionType(llvm::Type* ret_type, uint32_t method_idx,
2665 bool is_static) {
2666 // Get method signature
2667 art::DexFile::MethodId const& method_id =
2668 dex_compilation_unit_->GetDexFile()->GetMethodId(method_idx);
2669
2670 uint32_t shorty_size;
2671 const char* shorty = dex_compilation_unit_->GetDexFile()->GetMethodShorty(method_id, &shorty_size);
2672 CHECK_GE(shorty_size, 1u);
2673
2674 // Get argument type
2675 std::vector<llvm::Type*> args_type;
2676
2677 args_type.push_back(irb_.getJObjectTy()); // method object pointer
2678
2679 if (!is_static) {
2680 args_type.push_back(irb_.getJType('L')); // "this" object pointer
2681 }
2682
2683 for (uint32_t i = 1; i < shorty_size; ++i) {
2684 char shorty_type = art::RemapShorty(shorty[i]);
2685 args_type.push_back(irb_.getJType(shorty_type));
2686 }
2687
2688 return llvm::FunctionType::get(ret_type, args_type, false);
2689 }
2690
2691
2692 llvm::BasicBlock* GBCExpanderPass::
CreateBasicBlockWithDexPC(uint32_t dex_pc,const char * postfix)2693 CreateBasicBlockWithDexPC(uint32_t dex_pc, const char* postfix) {
2694 std::string name;
2695
2696 #if !defined(NDEBUG)
2697 art::StringAppendF(&name, "B%04x.%s", dex_pc, postfix);
2698 #endif
2699
2700 return llvm::BasicBlock::Create(context_, name, func_);
2701 }
2702
GetBasicBlock(uint32_t dex_pc)2703 llvm::BasicBlock* GBCExpanderPass::GetBasicBlock(uint32_t dex_pc) {
2704 DCHECK(dex_pc < dex_compilation_unit_->GetCodeItem()->insns_size_in_code_units_);
2705 CHECK(basic_blocks_[dex_pc] != NULL);
2706 return basic_blocks_[dex_pc];
2707 }
2708
GetTryItemOffset(uint32_t dex_pc)2709 int32_t GBCExpanderPass::GetTryItemOffset(uint32_t dex_pc) {
2710 int32_t min = 0;
2711 int32_t max = dex_compilation_unit_->GetCodeItem()->tries_size_ - 1;
2712
2713 while (min <= max) {
2714 int32_t mid = min + (max - min) / 2;
2715
2716 const art::DexFile::TryItem* ti =
2717 art::DexFile::GetTryItems(*dex_compilation_unit_->GetCodeItem(), mid);
2718 uint32_t start = ti->start_addr_;
2719 uint32_t end = start + ti->insn_count_;
2720
2721 if (dex_pc < start) {
2722 max = mid - 1;
2723 } else if (dex_pc >= end) {
2724 min = mid + 1;
2725 } else {
2726 return mid; // found
2727 }
2728 }
2729
2730 return -1; // not found
2731 }
2732
GetLandingPadBasicBlock(uint32_t dex_pc)2733 llvm::BasicBlock* GBCExpanderPass::GetLandingPadBasicBlock(uint32_t dex_pc) {
2734 // Find the try item for this address in this method
2735 int32_t ti_offset = GetTryItemOffset(dex_pc);
2736
2737 if (ti_offset == -1) {
2738 return NULL; // No landing pad is available for this address.
2739 }
2740
2741 // Check for the existing landing pad basic block
2742 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2743 llvm::BasicBlock* block_lpad = basic_block_landing_pads_[ti_offset];
2744
2745 if (block_lpad) {
2746 // We have generated landing pad for this try item already. Return the
2747 // same basic block.
2748 return block_lpad;
2749 }
2750
2751 // Get try item from code item
2752 const art::DexFile::TryItem* ti = art::DexFile::GetTryItems(*dex_compilation_unit_->GetCodeItem(),
2753 ti_offset);
2754
2755 std::string lpadname;
2756
2757 #if !defined(NDEBUG)
2758 art::StringAppendF(&lpadname, "lpad%d_%04x_to_%04x", ti_offset, ti->start_addr_, ti->handler_off_);
2759 #endif
2760
2761 // Create landing pad basic block
2762 block_lpad = llvm::BasicBlock::Create(context_, lpadname, func_);
2763
2764 // Change IRBuilder insert point
2765 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2766 irb_.SetInsertPoint(block_lpad);
2767
2768 // Find catch block with matching type
2769 llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
2770
2771 llvm::Value* ti_offset_value = irb_.getInt32(ti_offset);
2772
2773 llvm::Value* catch_handler_index_value =
2774 irb_.CreateCall2(irb_.GetRuntime(FindCatchBlock),
2775 method_object_addr, ti_offset_value);
2776
2777 // Switch instruction (Go to unwind basic block by default)
2778 llvm::SwitchInst* sw =
2779 irb_.CreateSwitch(catch_handler_index_value, GetUnwindBasicBlock());
2780
2781 // Cases with matched catch block
2782 art::CatchHandlerIterator iter(*dex_compilation_unit_->GetCodeItem(), ti->start_addr_);
2783
2784 for (uint32_t c = 0; iter.HasNext(); iter.Next(), ++c) {
2785 sw->addCase(irb_.getInt32(c), GetBasicBlock(iter.GetHandlerAddress()));
2786 }
2787
2788 // Restore the orignal insert point for IRBuilder
2789 irb_.restoreIP(irb_ip_original);
2790
2791 // Cache this landing pad
2792 DCHECK_GT(basic_block_landing_pads_.size(), static_cast<size_t>(ti_offset));
2793 basic_block_landing_pads_[ti_offset] = block_lpad;
2794
2795 return block_lpad;
2796 }
2797
GetUnwindBasicBlock()2798 llvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() {
2799 // Check the existing unwinding baisc block block
2800 if (basic_block_unwind_ != NULL) {
2801 return basic_block_unwind_;
2802 }
2803
2804 // Create new basic block for unwinding
2805 basic_block_unwind_ =
2806 llvm::BasicBlock::Create(context_, "exception_unwind", func_);
2807
2808 // Change IRBuilder insert point
2809 llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
2810 irb_.SetInsertPoint(basic_block_unwind_);
2811
2812 // Pop the shadow frame
2813 Expand_PopShadowFrame();
2814
2815 // Emit the code to return default value (zero) for the given return type.
2816 char ret_shorty = dex_compilation_unit_->GetShorty()[0];
2817 ret_shorty = art::RemapShorty(ret_shorty);
2818 if (ret_shorty == 'V') {
2819 irb_.CreateRetVoid();
2820 } else {
2821 irb_.CreateRet(irb_.getJZero(ret_shorty));
2822 }
2823
2824 // Restore the orignal insert point for IRBuilder
2825 irb_.restoreIP(irb_ip_original);
2826
2827 return basic_block_unwind_;
2828 }
2829
EmitBranchExceptionLandingPad(uint32_t dex_pc)2830 void GBCExpanderPass::EmitBranchExceptionLandingPad(uint32_t dex_pc) {
2831 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
2832 landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
2833 irb_.GetInsertBlock()));
2834 irb_.CreateBr(lpad);
2835 } else {
2836 irb_.CreateBr(GetUnwindBasicBlock());
2837 }
2838 }
2839
EmitGuard_ExceptionLandingPad(uint32_t dex_pc)2840 void GBCExpanderPass::EmitGuard_ExceptionLandingPad(uint32_t dex_pc) {
2841 llvm::Value* exception_pending = irb_.Runtime().EmitIsExceptionPending();
2842
2843 llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
2844
2845 if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
2846 landing_pad_phi_mapping_[lpad].push_back(std::make_pair(current_bb_->getUniquePredecessor(),
2847 irb_.GetInsertBlock()));
2848 irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
2849 } else {
2850 irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
2851 }
2852
2853 irb_.SetInsertPoint(block_cont);
2854 }
2855
2856 llvm::Value*
ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,llvm::CallInst & call_inst)2857 GBCExpanderPass::ExpandIntrinsic(IntrinsicHelper::IntrinsicId intr_id,
2858 llvm::CallInst& call_inst) {
2859 switch (intr_id) {
2860 //==- Thread -----------------------------------------------------------==//
2861 case IntrinsicHelper::GetCurrentThread: {
2862 return irb_.Runtime().EmitGetCurrentThread();
2863 }
2864 case IntrinsicHelper::CheckSuspend: {
2865 Expand_TestSuspend(call_inst);
2866 return NULL;
2867 }
2868 case IntrinsicHelper::TestSuspend: {
2869 Expand_TestSuspend(call_inst);
2870 return NULL;
2871 }
2872 case IntrinsicHelper::MarkGCCard: {
2873 Expand_MarkGCCard(call_inst);
2874 return NULL;
2875 }
2876
2877 //==- Exception --------------------------------------------------------==//
2878 case IntrinsicHelper::ThrowException: {
2879 return ExpandToRuntime(ThrowException, call_inst);
2880 }
2881 case IntrinsicHelper::HLThrowException: {
2882 uint32_t dex_pc = LV2UInt(call_inst.getMetadata("DexOff")->getOperand(0));
2883
2884 EmitUpdateDexPC(dex_pc);
2885
2886 irb_.CreateCall(irb_.GetRuntime(ThrowException),
2887 call_inst.getArgOperand(0));
2888
2889 EmitGuard_ExceptionLandingPad(dex_pc);
2890 return NULL;
2891 }
2892 case IntrinsicHelper::GetException: {
2893 return irb_.Runtime().EmitGetAndClearException();
2894 }
2895 case IntrinsicHelper::IsExceptionPending: {
2896 return irb_.Runtime().EmitIsExceptionPending();
2897 }
2898 case IntrinsicHelper::FindCatchBlock: {
2899 return ExpandToRuntime(FindCatchBlock, call_inst);
2900 }
2901 case IntrinsicHelper::ThrowDivZeroException: {
2902 return ExpandToRuntime(ThrowDivZeroException, call_inst);
2903 }
2904 case IntrinsicHelper::ThrowNullPointerException: {
2905 return ExpandToRuntime(ThrowNullPointerException, call_inst);
2906 }
2907 case IntrinsicHelper::ThrowIndexOutOfBounds: {
2908 return ExpandToRuntime(ThrowIndexOutOfBounds, call_inst);
2909 }
2910
2911 //==- Const String -----------------------------------------------------==//
2912 case IntrinsicHelper::ConstString: {
2913 return Expand_ConstString(call_inst);
2914 }
2915 case IntrinsicHelper::LoadStringFromDexCache: {
2916 return Expand_LoadStringFromDexCache(call_inst.getArgOperand(0));
2917 }
2918 case IntrinsicHelper::ResolveString: {
2919 return ExpandToRuntime(ResolveString, call_inst);
2920 }
2921
2922 //==- Const Class ------------------------------------------------------==//
2923 case IntrinsicHelper::ConstClass: {
2924 return Expand_ConstClass(call_inst);
2925 }
2926 case IntrinsicHelper::InitializeTypeAndVerifyAccess: {
2927 return ExpandToRuntime(InitializeTypeAndVerifyAccess, call_inst);
2928 }
2929 case IntrinsicHelper::LoadTypeFromDexCache: {
2930 return Expand_LoadTypeFromDexCache(call_inst.getArgOperand(0));
2931 }
2932 case IntrinsicHelper::InitializeType: {
2933 return ExpandToRuntime(InitializeType, call_inst);
2934 }
2935
2936 //==- Lock -------------------------------------------------------------==//
2937 case IntrinsicHelper::LockObject: {
2938 Expand_LockObject(call_inst.getArgOperand(0));
2939 return NULL;
2940 }
2941 case IntrinsicHelper::UnlockObject: {
2942 Expand_UnlockObject(call_inst.getArgOperand(0));
2943 return NULL;
2944 }
2945
2946 //==- Cast -------------------------------------------------------------==//
2947 case IntrinsicHelper::CheckCast: {
2948 return ExpandToRuntime(CheckCast, call_inst);
2949 }
2950 case IntrinsicHelper::HLCheckCast: {
2951 Expand_HLCheckCast(call_inst);
2952 return NULL;
2953 }
2954 case IntrinsicHelper::IsAssignable: {
2955 return ExpandToRuntime(IsAssignable, call_inst);
2956 }
2957
2958 //==- Alloc ------------------------------------------------------------==//
2959 case IntrinsicHelper::AllocObject: {
2960 return ExpandToRuntime(AllocObject, call_inst);
2961 }
2962 case IntrinsicHelper::AllocObjectWithAccessCheck: {
2963 return ExpandToRuntime(AllocObjectWithAccessCheck, call_inst);
2964 }
2965
2966 //==- Instance ---------------------------------------------------------==//
2967 case IntrinsicHelper::NewInstance: {
2968 return Expand_NewInstance(call_inst);
2969 }
2970 case IntrinsicHelper::InstanceOf: {
2971 return Expand_InstanceOf(call_inst);
2972 }
2973
2974 //==- Array ------------------------------------------------------------==//
2975 case IntrinsicHelper::NewArray: {
2976 return Expand_NewArray(call_inst);
2977 }
2978 case IntrinsicHelper::OptArrayLength: {
2979 return Expand_OptArrayLength(call_inst);
2980 }
2981 case IntrinsicHelper::ArrayLength: {
2982 return EmitLoadArrayLength(call_inst.getArgOperand(0));
2983 }
2984 case IntrinsicHelper::AllocArray: {
2985 return ExpandToRuntime(AllocArray, call_inst);
2986 }
2987 case IntrinsicHelper::AllocArrayWithAccessCheck: {
2988 return ExpandToRuntime(AllocArrayWithAccessCheck,
2989 call_inst);
2990 }
2991 case IntrinsicHelper::CheckAndAllocArray: {
2992 return ExpandToRuntime(CheckAndAllocArray, call_inst);
2993 }
2994 case IntrinsicHelper::CheckAndAllocArrayWithAccessCheck: {
2995 return ExpandToRuntime(CheckAndAllocArrayWithAccessCheck,
2996 call_inst);
2997 }
2998 case IntrinsicHelper::ArrayGet: {
2999 return Expand_ArrayGet(call_inst.getArgOperand(0),
3000 call_inst.getArgOperand(1),
3001 kInt);
3002 }
3003 case IntrinsicHelper::ArrayGetWide: {
3004 return Expand_ArrayGet(call_inst.getArgOperand(0),
3005 call_inst.getArgOperand(1),
3006 kLong);
3007 }
3008 case IntrinsicHelper::ArrayGetObject: {
3009 return Expand_ArrayGet(call_inst.getArgOperand(0),
3010 call_inst.getArgOperand(1),
3011 kObject);
3012 }
3013 case IntrinsicHelper::ArrayGetBoolean: {
3014 return Expand_ArrayGet(call_inst.getArgOperand(0),
3015 call_inst.getArgOperand(1),
3016 kBoolean);
3017 }
3018 case IntrinsicHelper::ArrayGetByte: {
3019 return Expand_ArrayGet(call_inst.getArgOperand(0),
3020 call_inst.getArgOperand(1),
3021 kByte);
3022 }
3023 case IntrinsicHelper::ArrayGetChar: {
3024 return Expand_ArrayGet(call_inst.getArgOperand(0),
3025 call_inst.getArgOperand(1),
3026 kChar);
3027 }
3028 case IntrinsicHelper::ArrayGetShort: {
3029 return Expand_ArrayGet(call_inst.getArgOperand(0),
3030 call_inst.getArgOperand(1),
3031 kShort);
3032 }
3033 case IntrinsicHelper::ArrayPut: {
3034 Expand_ArrayPut(call_inst.getArgOperand(0),
3035 call_inst.getArgOperand(1),
3036 call_inst.getArgOperand(2),
3037 kInt);
3038 return NULL;
3039 }
3040 case IntrinsicHelper::ArrayPutWide: {
3041 Expand_ArrayPut(call_inst.getArgOperand(0),
3042 call_inst.getArgOperand(1),
3043 call_inst.getArgOperand(2),
3044 kLong);
3045 return NULL;
3046 }
3047 case IntrinsicHelper::ArrayPutObject: {
3048 Expand_ArrayPut(call_inst.getArgOperand(0),
3049 call_inst.getArgOperand(1),
3050 call_inst.getArgOperand(2),
3051 kObject);
3052 return NULL;
3053 }
3054 case IntrinsicHelper::ArrayPutBoolean: {
3055 Expand_ArrayPut(call_inst.getArgOperand(0),
3056 call_inst.getArgOperand(1),
3057 call_inst.getArgOperand(2),
3058 kBoolean);
3059 return NULL;
3060 }
3061 case IntrinsicHelper::ArrayPutByte: {
3062 Expand_ArrayPut(call_inst.getArgOperand(0),
3063 call_inst.getArgOperand(1),
3064 call_inst.getArgOperand(2),
3065 kByte);
3066 return NULL;
3067 }
3068 case IntrinsicHelper::ArrayPutChar: {
3069 Expand_ArrayPut(call_inst.getArgOperand(0),
3070 call_inst.getArgOperand(1),
3071 call_inst.getArgOperand(2),
3072 kChar);
3073 return NULL;
3074 }
3075 case IntrinsicHelper::ArrayPutShort: {
3076 Expand_ArrayPut(call_inst.getArgOperand(0),
3077 call_inst.getArgOperand(1),
3078 call_inst.getArgOperand(2),
3079 kShort);
3080 return NULL;
3081 }
3082 case IntrinsicHelper::CheckPutArrayElement: {
3083 return ExpandToRuntime(CheckPutArrayElement, call_inst);
3084 }
3085 case IntrinsicHelper::FilledNewArray: {
3086 Expand_FilledNewArray(call_inst);
3087 return NULL;
3088 }
3089 case IntrinsicHelper::FillArrayData: {
3090 return ExpandToRuntime(FillArrayData, call_inst);
3091 }
3092 case IntrinsicHelper::HLFillArrayData: {
3093 Expand_HLFillArrayData(call_inst);
3094 return NULL;
3095 }
3096 case IntrinsicHelper::HLFilledNewArray: {
3097 return Expand_HLFilledNewArray(call_inst);
3098 }
3099
3100 //==- Instance Field ---------------------------------------------------==//
3101 case IntrinsicHelper::InstanceFieldGet:
3102 case IntrinsicHelper::InstanceFieldGetBoolean:
3103 case IntrinsicHelper::InstanceFieldGetByte:
3104 case IntrinsicHelper::InstanceFieldGetChar:
3105 case IntrinsicHelper::InstanceFieldGetShort: {
3106 return ExpandToRuntime(Get32Instance, call_inst);
3107 }
3108 case IntrinsicHelper::InstanceFieldGetWide: {
3109 return ExpandToRuntime(Get64Instance, call_inst);
3110 }
3111 case IntrinsicHelper::InstanceFieldGetObject: {
3112 return ExpandToRuntime(GetObjectInstance, call_inst);
3113 }
3114 case IntrinsicHelper::InstanceFieldGetFast: {
3115 return Expand_IGetFast(call_inst.getArgOperand(0),
3116 call_inst.getArgOperand(1),
3117 call_inst.getArgOperand(2),
3118 kInt);
3119 }
3120 case IntrinsicHelper::InstanceFieldGetWideFast: {
3121 return Expand_IGetFast(call_inst.getArgOperand(0),
3122 call_inst.getArgOperand(1),
3123 call_inst.getArgOperand(2),
3124 kLong);
3125 }
3126 case IntrinsicHelper::InstanceFieldGetObjectFast: {
3127 return Expand_IGetFast(call_inst.getArgOperand(0),
3128 call_inst.getArgOperand(1),
3129 call_inst.getArgOperand(2),
3130 kObject);
3131 }
3132 case IntrinsicHelper::InstanceFieldGetBooleanFast: {
3133 return Expand_IGetFast(call_inst.getArgOperand(0),
3134 call_inst.getArgOperand(1),
3135 call_inst.getArgOperand(2),
3136 kBoolean);
3137 }
3138 case IntrinsicHelper::InstanceFieldGetByteFast: {
3139 return Expand_IGetFast(call_inst.getArgOperand(0),
3140 call_inst.getArgOperand(1),
3141 call_inst.getArgOperand(2),
3142 kByte);
3143 }
3144 case IntrinsicHelper::InstanceFieldGetCharFast: {
3145 return Expand_IGetFast(call_inst.getArgOperand(0),
3146 call_inst.getArgOperand(1),
3147 call_inst.getArgOperand(2),
3148 kChar);
3149 }
3150 case IntrinsicHelper::InstanceFieldGetShortFast: {
3151 return Expand_IGetFast(call_inst.getArgOperand(0),
3152 call_inst.getArgOperand(1),
3153 call_inst.getArgOperand(2),
3154 kShort);
3155 }
3156 case IntrinsicHelper::InstanceFieldPut:
3157 case IntrinsicHelper::InstanceFieldPutBoolean:
3158 case IntrinsicHelper::InstanceFieldPutByte:
3159 case IntrinsicHelper::InstanceFieldPutChar:
3160 case IntrinsicHelper::InstanceFieldPutShort: {
3161 return ExpandToRuntime(Set32Instance, call_inst);
3162 }
3163 case IntrinsicHelper::InstanceFieldPutWide: {
3164 return ExpandToRuntime(Set64Instance, call_inst);
3165 }
3166 case IntrinsicHelper::InstanceFieldPutObject: {
3167 return ExpandToRuntime(SetObjectInstance, call_inst);
3168 }
3169 case IntrinsicHelper::InstanceFieldPutFast: {
3170 Expand_IPutFast(call_inst.getArgOperand(0),
3171 call_inst.getArgOperand(1),
3172 call_inst.getArgOperand(2),
3173 call_inst.getArgOperand(3),
3174 kInt);
3175 return NULL;
3176 }
3177 case IntrinsicHelper::InstanceFieldPutWideFast: {
3178 Expand_IPutFast(call_inst.getArgOperand(0),
3179 call_inst.getArgOperand(1),
3180 call_inst.getArgOperand(2),
3181 call_inst.getArgOperand(3),
3182 kLong);
3183 return NULL;
3184 }
3185 case IntrinsicHelper::InstanceFieldPutObjectFast: {
3186 Expand_IPutFast(call_inst.getArgOperand(0),
3187 call_inst.getArgOperand(1),
3188 call_inst.getArgOperand(2),
3189 call_inst.getArgOperand(3),
3190 kObject);
3191 return NULL;
3192 }
3193 case IntrinsicHelper::InstanceFieldPutBooleanFast: {
3194 Expand_IPutFast(call_inst.getArgOperand(0),
3195 call_inst.getArgOperand(1),
3196 call_inst.getArgOperand(2),
3197 call_inst.getArgOperand(3),
3198 kBoolean);
3199 return NULL;
3200 }
3201 case IntrinsicHelper::InstanceFieldPutByteFast: {
3202 Expand_IPutFast(call_inst.getArgOperand(0),
3203 call_inst.getArgOperand(1),
3204 call_inst.getArgOperand(2),
3205 call_inst.getArgOperand(3),
3206 kByte);
3207 return NULL;
3208 }
3209 case IntrinsicHelper::InstanceFieldPutCharFast: {
3210 Expand_IPutFast(call_inst.getArgOperand(0),
3211 call_inst.getArgOperand(1),
3212 call_inst.getArgOperand(2),
3213 call_inst.getArgOperand(3),
3214 kChar);
3215 return NULL;
3216 }
3217 case IntrinsicHelper::InstanceFieldPutShortFast: {
3218 Expand_IPutFast(call_inst.getArgOperand(0),
3219 call_inst.getArgOperand(1),
3220 call_inst.getArgOperand(2),
3221 call_inst.getArgOperand(3),
3222 kShort);
3223 return NULL;
3224 }
3225
3226 //==- Static Field -----------------------------------------------------==//
3227 case IntrinsicHelper::StaticFieldGet:
3228 case IntrinsicHelper::StaticFieldGetBoolean:
3229 case IntrinsicHelper::StaticFieldGetByte:
3230 case IntrinsicHelper::StaticFieldGetChar:
3231 case IntrinsicHelper::StaticFieldGetShort: {
3232 return ExpandToRuntime(Get32Static, call_inst);
3233 }
3234 case IntrinsicHelper::StaticFieldGetWide: {
3235 return ExpandToRuntime(Get64Static, call_inst);
3236 }
3237 case IntrinsicHelper::StaticFieldGetObject: {
3238 return ExpandToRuntime(GetObjectStatic, call_inst);
3239 }
3240 case IntrinsicHelper::StaticFieldGetFast: {
3241 return Expand_SGetFast(call_inst.getArgOperand(0),
3242 call_inst.getArgOperand(1),
3243 call_inst.getArgOperand(2),
3244 kInt);
3245 }
3246 case IntrinsicHelper::StaticFieldGetWideFast: {
3247 return Expand_SGetFast(call_inst.getArgOperand(0),
3248 call_inst.getArgOperand(1),
3249 call_inst.getArgOperand(2),
3250 kLong);
3251 }
3252 case IntrinsicHelper::StaticFieldGetObjectFast: {
3253 return Expand_SGetFast(call_inst.getArgOperand(0),
3254 call_inst.getArgOperand(1),
3255 call_inst.getArgOperand(2),
3256 kObject);
3257 }
3258 case IntrinsicHelper::StaticFieldGetBooleanFast: {
3259 return Expand_SGetFast(call_inst.getArgOperand(0),
3260 call_inst.getArgOperand(1),
3261 call_inst.getArgOperand(2),
3262 kBoolean);
3263 }
3264 case IntrinsicHelper::StaticFieldGetByteFast: {
3265 return Expand_SGetFast(call_inst.getArgOperand(0),
3266 call_inst.getArgOperand(1),
3267 call_inst.getArgOperand(2),
3268 kByte);
3269 }
3270 case IntrinsicHelper::StaticFieldGetCharFast: {
3271 return Expand_SGetFast(call_inst.getArgOperand(0),
3272 call_inst.getArgOperand(1),
3273 call_inst.getArgOperand(2),
3274 kChar);
3275 }
3276 case IntrinsicHelper::StaticFieldGetShortFast: {
3277 return Expand_SGetFast(call_inst.getArgOperand(0),
3278 call_inst.getArgOperand(1),
3279 call_inst.getArgOperand(2),
3280 kShort);
3281 }
3282 case IntrinsicHelper::StaticFieldPut:
3283 case IntrinsicHelper::StaticFieldPutBoolean:
3284 case IntrinsicHelper::StaticFieldPutByte:
3285 case IntrinsicHelper::StaticFieldPutChar:
3286 case IntrinsicHelper::StaticFieldPutShort: {
3287 return ExpandToRuntime(Set32Static, call_inst);
3288 }
3289 case IntrinsicHelper::StaticFieldPutWide: {
3290 return ExpandToRuntime(Set64Static, call_inst);
3291 }
3292 case IntrinsicHelper::StaticFieldPutObject: {
3293 return ExpandToRuntime(SetObjectStatic, call_inst);
3294 }
3295 case IntrinsicHelper::StaticFieldPutFast: {
3296 Expand_SPutFast(call_inst.getArgOperand(0),
3297 call_inst.getArgOperand(1),
3298 call_inst.getArgOperand(2),
3299 call_inst.getArgOperand(3),
3300 kInt);
3301 return NULL;
3302 }
3303 case IntrinsicHelper::StaticFieldPutWideFast: {
3304 Expand_SPutFast(call_inst.getArgOperand(0),
3305 call_inst.getArgOperand(1),
3306 call_inst.getArgOperand(2),
3307 call_inst.getArgOperand(3),
3308 kLong);
3309 return NULL;
3310 }
3311 case IntrinsicHelper::StaticFieldPutObjectFast: {
3312 Expand_SPutFast(call_inst.getArgOperand(0),
3313 call_inst.getArgOperand(1),
3314 call_inst.getArgOperand(2),
3315 call_inst.getArgOperand(3),
3316 kObject);
3317 return NULL;
3318 }
3319 case IntrinsicHelper::StaticFieldPutBooleanFast: {
3320 Expand_SPutFast(call_inst.getArgOperand(0),
3321 call_inst.getArgOperand(1),
3322 call_inst.getArgOperand(2),
3323 call_inst.getArgOperand(3),
3324 kBoolean);
3325 return NULL;
3326 }
3327 case IntrinsicHelper::StaticFieldPutByteFast: {
3328 Expand_SPutFast(call_inst.getArgOperand(0),
3329 call_inst.getArgOperand(1),
3330 call_inst.getArgOperand(2),
3331 call_inst.getArgOperand(3),
3332 kByte);
3333 return NULL;
3334 }
3335 case IntrinsicHelper::StaticFieldPutCharFast: {
3336 Expand_SPutFast(call_inst.getArgOperand(0),
3337 call_inst.getArgOperand(1),
3338 call_inst.getArgOperand(2),
3339 call_inst.getArgOperand(3),
3340 kChar);
3341 return NULL;
3342 }
3343 case IntrinsicHelper::StaticFieldPutShortFast: {
3344 Expand_SPutFast(call_inst.getArgOperand(0),
3345 call_inst.getArgOperand(1),
3346 call_inst.getArgOperand(2),
3347 call_inst.getArgOperand(3),
3348 kShort);
3349 return NULL;
3350 }
3351 case IntrinsicHelper::LoadDeclaringClassSSB: {
3352 return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
3353 }
3354 case IntrinsicHelper::InitializeAndLoadClassSSB: {
3355 return ExpandToRuntime(InitializeStaticStorage, call_inst);
3356 }
3357
3358 //==- High-level Array -------------------------------------------------==//
3359 case IntrinsicHelper::HLArrayGet: {
3360 return Expand_HLArrayGet(call_inst, kInt);
3361 }
3362 case IntrinsicHelper::HLArrayGetBoolean: {
3363 return Expand_HLArrayGet(call_inst, kBoolean);
3364 }
3365 case IntrinsicHelper::HLArrayGetByte: {
3366 return Expand_HLArrayGet(call_inst, kByte);
3367 }
3368 case IntrinsicHelper::HLArrayGetChar: {
3369 return Expand_HLArrayGet(call_inst, kChar);
3370 }
3371 case IntrinsicHelper::HLArrayGetShort: {
3372 return Expand_HLArrayGet(call_inst, kShort);
3373 }
3374 case IntrinsicHelper::HLArrayGetFloat: {
3375 return Expand_HLArrayGet(call_inst, kFloat);
3376 }
3377 case IntrinsicHelper::HLArrayGetWide: {
3378 return Expand_HLArrayGet(call_inst, kLong);
3379 }
3380 case IntrinsicHelper::HLArrayGetDouble: {
3381 return Expand_HLArrayGet(call_inst, kDouble);
3382 }
3383 case IntrinsicHelper::HLArrayGetObject: {
3384 return Expand_HLArrayGet(call_inst, kObject);
3385 }
3386 case IntrinsicHelper::HLArrayPut: {
3387 Expand_HLArrayPut(call_inst, kInt);
3388 return NULL;
3389 }
3390 case IntrinsicHelper::HLArrayPutBoolean: {
3391 Expand_HLArrayPut(call_inst, kBoolean);
3392 return NULL;
3393 }
3394 case IntrinsicHelper::HLArrayPutByte: {
3395 Expand_HLArrayPut(call_inst, kByte);
3396 return NULL;
3397 }
3398 case IntrinsicHelper::HLArrayPutChar: {
3399 Expand_HLArrayPut(call_inst, kChar);
3400 return NULL;
3401 }
3402 case IntrinsicHelper::HLArrayPutShort: {
3403 Expand_HLArrayPut(call_inst, kShort);
3404 return NULL;
3405 }
3406 case IntrinsicHelper::HLArrayPutFloat: {
3407 Expand_HLArrayPut(call_inst, kFloat);
3408 return NULL;
3409 }
3410 case IntrinsicHelper::HLArrayPutWide: {
3411 Expand_HLArrayPut(call_inst, kLong);
3412 return NULL;
3413 }
3414 case IntrinsicHelper::HLArrayPutDouble: {
3415 Expand_HLArrayPut(call_inst, kDouble);
3416 return NULL;
3417 }
3418 case IntrinsicHelper::HLArrayPutObject: {
3419 Expand_HLArrayPut(call_inst, kObject);
3420 return NULL;
3421 }
3422
3423 //==- High-level Instance ----------------------------------------------==//
3424 case IntrinsicHelper::HLIGet: {
3425 return Expand_HLIGet(call_inst, kInt);
3426 }
3427 case IntrinsicHelper::HLIGetBoolean: {
3428 return Expand_HLIGet(call_inst, kBoolean);
3429 }
3430 case IntrinsicHelper::HLIGetByte: {
3431 return Expand_HLIGet(call_inst, kByte);
3432 }
3433 case IntrinsicHelper::HLIGetChar: {
3434 return Expand_HLIGet(call_inst, kChar);
3435 }
3436 case IntrinsicHelper::HLIGetShort: {
3437 return Expand_HLIGet(call_inst, kShort);
3438 }
3439 case IntrinsicHelper::HLIGetFloat: {
3440 return Expand_HLIGet(call_inst, kFloat);
3441 }
3442 case IntrinsicHelper::HLIGetWide: {
3443 return Expand_HLIGet(call_inst, kLong);
3444 }
3445 case IntrinsicHelper::HLIGetDouble: {
3446 return Expand_HLIGet(call_inst, kDouble);
3447 }
3448 case IntrinsicHelper::HLIGetObject: {
3449 return Expand_HLIGet(call_inst, kObject);
3450 }
3451 case IntrinsicHelper::HLIPut: {
3452 Expand_HLIPut(call_inst, kInt);
3453 return NULL;
3454 }
3455 case IntrinsicHelper::HLIPutBoolean: {
3456 Expand_HLIPut(call_inst, kBoolean);
3457 return NULL;
3458 }
3459 case IntrinsicHelper::HLIPutByte: {
3460 Expand_HLIPut(call_inst, kByte);
3461 return NULL;
3462 }
3463 case IntrinsicHelper::HLIPutChar: {
3464 Expand_HLIPut(call_inst, kChar);
3465 return NULL;
3466 }
3467 case IntrinsicHelper::HLIPutShort: {
3468 Expand_HLIPut(call_inst, kShort);
3469 return NULL;
3470 }
3471 case IntrinsicHelper::HLIPutFloat: {
3472 Expand_HLIPut(call_inst, kFloat);
3473 return NULL;
3474 }
3475 case IntrinsicHelper::HLIPutWide: {
3476 Expand_HLIPut(call_inst, kLong);
3477 return NULL;
3478 }
3479 case IntrinsicHelper::HLIPutDouble: {
3480 Expand_HLIPut(call_inst, kDouble);
3481 return NULL;
3482 }
3483 case IntrinsicHelper::HLIPutObject: {
3484 Expand_HLIPut(call_inst, kObject);
3485 return NULL;
3486 }
3487
3488 //==- High-level Invoke ------------------------------------------------==//
3489 case IntrinsicHelper::HLInvokeVoid:
3490 case IntrinsicHelper::HLInvokeObj:
3491 case IntrinsicHelper::HLInvokeInt:
3492 case IntrinsicHelper::HLInvokeFloat:
3493 case IntrinsicHelper::HLInvokeLong:
3494 case IntrinsicHelper::HLInvokeDouble: {
3495 return Expand_HLInvoke(call_inst);
3496 }
3497
3498 //==- Invoke -----------------------------------------------------------==//
3499 case IntrinsicHelper::FindStaticMethodWithAccessCheck: {
3500 return ExpandToRuntime(FindStaticMethodWithAccessCheck, call_inst);
3501 }
3502 case IntrinsicHelper::FindDirectMethodWithAccessCheck: {
3503 return ExpandToRuntime(FindDirectMethodWithAccessCheck, call_inst);
3504 }
3505 case IntrinsicHelper::FindVirtualMethodWithAccessCheck: {
3506 return ExpandToRuntime(FindVirtualMethodWithAccessCheck, call_inst);
3507 }
3508 case IntrinsicHelper::FindSuperMethodWithAccessCheck: {
3509 return ExpandToRuntime(FindSuperMethodWithAccessCheck, call_inst);
3510 }
3511 case IntrinsicHelper::FindInterfaceMethodWithAccessCheck: {
3512 return ExpandToRuntime(FindInterfaceMethodWithAccessCheck, call_inst);
3513 }
3514 case IntrinsicHelper::GetSDCalleeMethodObjAddrFast: {
3515 return Expand_GetSDCalleeMethodObjAddrFast(call_inst.getArgOperand(0));
3516 }
3517 case IntrinsicHelper::GetVirtualCalleeMethodObjAddrFast: {
3518 return Expand_GetVirtualCalleeMethodObjAddrFast(
3519 call_inst.getArgOperand(0), call_inst.getArgOperand(1));
3520 }
3521 case IntrinsicHelper::GetInterfaceCalleeMethodObjAddrFast: {
3522 return ExpandToRuntime(FindInterfaceMethod, call_inst);
3523 }
3524 case IntrinsicHelper::InvokeRetVoid:
3525 case IntrinsicHelper::InvokeRetBoolean:
3526 case IntrinsicHelper::InvokeRetByte:
3527 case IntrinsicHelper::InvokeRetChar:
3528 case IntrinsicHelper::InvokeRetShort:
3529 case IntrinsicHelper::InvokeRetInt:
3530 case IntrinsicHelper::InvokeRetLong:
3531 case IntrinsicHelper::InvokeRetFloat:
3532 case IntrinsicHelper::InvokeRetDouble:
3533 case IntrinsicHelper::InvokeRetObject: {
3534 return Expand_Invoke(call_inst);
3535 }
3536
3537 //==- Math -------------------------------------------------------------==//
3538 case IntrinsicHelper::DivInt: {
3539 return Expand_DivRem(call_inst, /* is_div */true, kInt);
3540 }
3541 case IntrinsicHelper::RemInt: {
3542 return Expand_DivRem(call_inst, /* is_div */false, kInt);
3543 }
3544 case IntrinsicHelper::DivLong: {
3545 return Expand_DivRem(call_inst, /* is_div */true, kLong);
3546 }
3547 case IntrinsicHelper::RemLong: {
3548 return Expand_DivRem(call_inst, /* is_div */false, kLong);
3549 }
3550 case IntrinsicHelper::D2L: {
3551 return ExpandToRuntime(art_d2l, call_inst);
3552 }
3553 case IntrinsicHelper::D2I: {
3554 return ExpandToRuntime(art_d2i, call_inst);
3555 }
3556 case IntrinsicHelper::F2L: {
3557 return ExpandToRuntime(art_f2l, call_inst);
3558 }
3559 case IntrinsicHelper::F2I: {
3560 return ExpandToRuntime(art_f2i, call_inst);
3561 }
3562
3563 //==- High-level Static ------------------------------------------------==//
3564 case IntrinsicHelper::HLSget: {
3565 return Expand_HLSget(call_inst, kInt);
3566 }
3567 case IntrinsicHelper::HLSgetBoolean: {
3568 return Expand_HLSget(call_inst, kBoolean);
3569 }
3570 case IntrinsicHelper::HLSgetByte: {
3571 return Expand_HLSget(call_inst, kByte);
3572 }
3573 case IntrinsicHelper::HLSgetChar: {
3574 return Expand_HLSget(call_inst, kChar);
3575 }
3576 case IntrinsicHelper::HLSgetShort: {
3577 return Expand_HLSget(call_inst, kShort);
3578 }
3579 case IntrinsicHelper::HLSgetFloat: {
3580 return Expand_HLSget(call_inst, kFloat);
3581 }
3582 case IntrinsicHelper::HLSgetWide: {
3583 return Expand_HLSget(call_inst, kLong);
3584 }
3585 case IntrinsicHelper::HLSgetDouble: {
3586 return Expand_HLSget(call_inst, kDouble);
3587 }
3588 case IntrinsicHelper::HLSgetObject: {
3589 return Expand_HLSget(call_inst, kObject);
3590 }
3591 case IntrinsicHelper::HLSput: {
3592 Expand_HLSput(call_inst, kInt);
3593 return NULL;
3594 }
3595 case IntrinsicHelper::HLSputBoolean: {
3596 Expand_HLSput(call_inst, kBoolean);
3597 return NULL;
3598 }
3599 case IntrinsicHelper::HLSputByte: {
3600 Expand_HLSput(call_inst, kByte);
3601 return NULL;
3602 }
3603 case IntrinsicHelper::HLSputChar: {
3604 Expand_HLSput(call_inst, kChar);
3605 return NULL;
3606 }
3607 case IntrinsicHelper::HLSputShort: {
3608 Expand_HLSput(call_inst, kShort);
3609 return NULL;
3610 }
3611 case IntrinsicHelper::HLSputFloat: {
3612 Expand_HLSput(call_inst, kFloat);
3613 return NULL;
3614 }
3615 case IntrinsicHelper::HLSputWide: {
3616 Expand_HLSput(call_inst, kLong);
3617 return NULL;
3618 }
3619 case IntrinsicHelper::HLSputDouble: {
3620 Expand_HLSput(call_inst, kDouble);
3621 return NULL;
3622 }
3623 case IntrinsicHelper::HLSputObject: {
3624 Expand_HLSput(call_inst, kObject);
3625 return NULL;
3626 }
3627
3628 //==- High-level Monitor -----------------------------------------------==//
3629 case IntrinsicHelper::MonitorEnter: {
3630 Expand_MonitorEnter(call_inst);
3631 return NULL;
3632 }
3633 case IntrinsicHelper::MonitorExit: {
3634 Expand_MonitorExit(call_inst);
3635 return NULL;
3636 }
3637
3638 //==- Shadow Frame -----------------------------------------------------==//
3639 case IntrinsicHelper::AllocaShadowFrame: {
3640 Expand_AllocaShadowFrame(call_inst.getArgOperand(0));
3641 return NULL;
3642 }
3643 case IntrinsicHelper::SetVReg: {
3644 Expand_SetVReg(call_inst.getArgOperand(0),
3645 call_inst.getArgOperand(1));
3646 return NULL;
3647 }
3648 case IntrinsicHelper::PopShadowFrame: {
3649 Expand_PopShadowFrame();
3650 return NULL;
3651 }
3652 case IntrinsicHelper::UpdateDexPC: {
3653 Expand_UpdateDexPC(call_inst.getArgOperand(0));
3654 return NULL;
3655 }
3656
3657 //==- Comparison -------------------------------------------------------==//
3658 case IntrinsicHelper::CmplFloat:
3659 case IntrinsicHelper::CmplDouble: {
3660 return Expand_FPCompare(call_inst.getArgOperand(0),
3661 call_inst.getArgOperand(1),
3662 false);
3663 }
3664 case IntrinsicHelper::CmpgFloat:
3665 case IntrinsicHelper::CmpgDouble: {
3666 return Expand_FPCompare(call_inst.getArgOperand(0),
3667 call_inst.getArgOperand(1),
3668 true);
3669 }
3670 case IntrinsicHelper::CmpLong: {
3671 return Expand_LongCompare(call_inst.getArgOperand(0),
3672 call_inst.getArgOperand(1));
3673 }
3674
3675 //==- Const ------------------------------------------------------------==//
3676 case IntrinsicHelper::ConstInt:
3677 case IntrinsicHelper::ConstLong: {
3678 return call_inst.getArgOperand(0);
3679 }
3680 case IntrinsicHelper::ConstFloat: {
3681 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3682 irb_.getJFloatTy());
3683 }
3684 case IntrinsicHelper::ConstDouble: {
3685 return irb_.CreateBitCast(call_inst.getArgOperand(0),
3686 irb_.getJDoubleTy());
3687 }
3688 case IntrinsicHelper::ConstObj: {
3689 CHECK_EQ(LV2UInt(call_inst.getArgOperand(0)), 0U);
3690 return irb_.getJNull();
3691 }
3692
3693 //==- Method Info ------------------------------------------------------==//
3694 case IntrinsicHelper::MethodInfo: {
3695 // Nothing to be done, because MethodInfo carries optional hints that are
3696 // not needed by the portable path.
3697 return NULL;
3698 }
3699
3700 //==- Copy -------------------------------------------------------------==//
3701 case IntrinsicHelper::CopyInt:
3702 case IntrinsicHelper::CopyFloat:
3703 case IntrinsicHelper::CopyLong:
3704 case IntrinsicHelper::CopyDouble:
3705 case IntrinsicHelper::CopyObj: {
3706 return call_inst.getArgOperand(0);
3707 }
3708
3709 //==- Shift ------------------------------------------------------------==//
3710 case IntrinsicHelper::SHLLong: {
3711 return Expand_IntegerShift(call_inst.getArgOperand(0),
3712 call_inst.getArgOperand(1),
3713 kIntegerSHL, kLong);
3714 }
3715 case IntrinsicHelper::SHRLong: {
3716 return Expand_IntegerShift(call_inst.getArgOperand(0),
3717 call_inst.getArgOperand(1),
3718 kIntegerSHR, kLong);
3719 }
3720 case IntrinsicHelper::USHRLong: {
3721 return Expand_IntegerShift(call_inst.getArgOperand(0),
3722 call_inst.getArgOperand(1),
3723 kIntegerUSHR, kLong);
3724 }
3725 case IntrinsicHelper::SHLInt: {
3726 return Expand_IntegerShift(call_inst.getArgOperand(0),
3727 call_inst.getArgOperand(1),
3728 kIntegerSHL, kInt);
3729 }
3730 case IntrinsicHelper::SHRInt: {
3731 return Expand_IntegerShift(call_inst.getArgOperand(0),
3732 call_inst.getArgOperand(1),
3733 kIntegerSHR, kInt);
3734 }
3735 case IntrinsicHelper::USHRInt: {
3736 return Expand_IntegerShift(call_inst.getArgOperand(0),
3737 call_inst.getArgOperand(1),
3738 kIntegerUSHR, kInt);
3739 }
3740
3741 //==- Conversion -------------------------------------------------------==//
3742 case IntrinsicHelper::IntToChar: {
3743 return irb_.CreateZExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJCharTy()),
3744 irb_.getJIntTy());
3745 }
3746 case IntrinsicHelper::IntToShort: {
3747 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJShortTy()),
3748 irb_.getJIntTy());
3749 }
3750 case IntrinsicHelper::IntToByte: {
3751 return irb_.CreateSExt(irb_.CreateTrunc(call_inst.getArgOperand(0), irb_.getJByteTy()),
3752 irb_.getJIntTy());
3753 }
3754
3755 //==- Exception --------------------------------------------------------==//
3756 case IntrinsicHelper::CatchTargets: {
3757 UpdatePhiInstruction(current_bb_, irb_.GetInsertBlock());
3758 llvm::SwitchInst* si = llvm::dyn_cast<llvm::SwitchInst>(call_inst.getNextNode());
3759 CHECK(si != NULL);
3760 irb_.CreateBr(si->getDefaultDest());
3761 si->eraseFromParent();
3762 return call_inst.getArgOperand(0);
3763 }
3764
3765 //==- Constructor barrier-----------------------------------------------==//
3766 case IntrinsicHelper::ConstructorBarrier: {
3767 irb_.CreateMemoryBarrier(art::kStoreStore);
3768 return NULL;
3769 }
3770
3771 //==- Unknown Cases ----------------------------------------------------==//
3772 case IntrinsicHelper::MaxIntrinsicId:
3773 case IntrinsicHelper::UnknownId:
3774 // default:
3775 // NOTE: "default" is intentionally commented so that C/C++ compiler will
3776 // give some warning on unmatched cases.
3777 // NOTE: We should not implement these cases.
3778 break;
3779 }
3780 UNIMPLEMENTED(FATAL) << "Unexpected GBC intrinsic: " << static_cast<int>(intr_id);
3781 return NULL;
3782 } // NOLINT(readability/fn_size)
3783
3784 } // anonymous namespace
3785
3786 namespace art {
3787 namespace llvm {
3788
3789 ::llvm::FunctionPass*
CreateGBCExpanderPass(const IntrinsicHelper & intrinsic_helper,IRBuilder & irb,CompilerDriver * driver,const DexCompilationUnit * dex_compilation_unit)3790 CreateGBCExpanderPass(const IntrinsicHelper& intrinsic_helper, IRBuilder& irb,
3791 CompilerDriver* driver, const DexCompilationUnit* dex_compilation_unit) {
3792 return new GBCExpanderPass(intrinsic_helper, irb, driver, dex_compilation_unit);
3793 }
3794
3795 } // namespace llvm
3796 } // namespace art
3797