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