diff options
Diffstat (limited to 'src/compiler')
| -rw-r--r-- | src/compiler/codegen/mir_to_gbc.cc | 207 | ||||
| -rw-r--r-- | src/compiler/frontend.h | 1 |
2 files changed, 121 insertions, 87 deletions
diff --git a/src/compiler/codegen/mir_to_gbc.cc b/src/compiler/codegen/mir_to_gbc.cc index e1e1fb16a5..766a630a0c 100644 --- a/src/compiler/codegen/mir_to_gbc.cc +++ b/src/compiler/codegen/mir_to_gbc.cc @@ -50,8 +50,22 @@ static llvm::Value* GetLLVMValue(CompilationUnit* cu, int s_reg) return reinterpret_cast<llvm::Value*>(GrowableListGetElement(&cu->llvm_values, s_reg)); } +static void SetVregOnValue(CompilationUnit* cu, llvm::Value* val, int s_reg) +{ + // Set vreg for debugging + if (cu->compiler->IsDebuggingSupported()) { + greenland::IntrinsicHelper::IntrinsicId id = + greenland::IntrinsicHelper::SetVReg; + llvm::Function* func = cu->intrinsic_helper->GetIntrinsicFunction(id); + int v_reg = SRegToVReg(cu, s_reg); + llvm::Value* table_slot = cu->irb->getInt32(v_reg); + llvm::Value* args[] = { table_slot, val }; + cu->irb->CreateCall(func, args); + } +} + // Replace the placeholder value with the real definition -static void DefineValue(CompilationUnit* cu, llvm::Value* val, int s_reg) +static void DefineValueOnly(CompilationUnit* cu, llvm::Value* val, int s_reg) { llvm::Value* placeholder = GetLLVMValue(cu, s_reg); if (placeholder == NULL) { @@ -66,16 +80,12 @@ static void DefineValue(CompilationUnit* cu, llvm::Value* val, int s_reg) DCHECK(inst != NULL); inst->eraseFromParent(); - // Set vreg for debugging - if (!cu->compiler->IsDebuggingSupported()) { - greenland::IntrinsicHelper::IntrinsicId id = - greenland::IntrinsicHelper::SetVReg; - llvm::Function* func = cu->intrinsic_helper->GetIntrinsicFunction(id); - int v_reg = SRegToVReg(cu, s_reg); - llvm::Value* table_slot = cu->irb->getInt32(v_reg); - llvm::Value* args[] = { table_slot, val }; - cu->irb->CreateCall(func, args); - } +} + +static void DefineValue(CompilationUnit* cu, llvm::Value* val, int s_reg) +{ + DefineValueOnly(cu, val, s_reg); + SetVregOnValue(cu, val, s_reg); } static llvm::Type* LlvmTypeFromLocRec(CompilationUnit* cu, RegLocation loc) @@ -1625,6 +1635,97 @@ static bool ConvertMIRNode(CompilationUnit* cu, MIR* mir, BasicBlock* bb, return res; } +static void SetDexOffset(CompilationUnit* cu, int32_t offset) +{ + cu->current_dalvik_offset = offset; + llvm::SmallVector<llvm::Value*, 1> array_ref; + array_ref.push_back(cu->irb->getInt32(offset)); + llvm::MDNode* node = llvm::MDNode::get(*cu->context, array_ref); + cu->irb->SetDexOffset(node); +} + +// Attach method info as metadata to special intrinsic +static void SetMethodInfo(CompilationUnit* cu) +{ + // We don't want dex offset on this + cu->irb->SetDexOffset(NULL); + greenland::IntrinsicHelper::IntrinsicId id; + id = greenland::IntrinsicHelper::MethodInfo; + llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); + llvm::Instruction* inst = cu->irb->CreateCall(intr); + llvm::SmallVector<llvm::Value*, 2> reg_info; + reg_info.push_back(cu->irb->getInt32(cu->num_ins)); + reg_info.push_back(cu->irb->getInt32(cu->num_regs)); + reg_info.push_back(cu->irb->getInt32(cu->num_outs)); + reg_info.push_back(cu->irb->getInt32(cu->num_compiler_temps)); + reg_info.push_back(cu->irb->getInt32(cu->num_ssa_regs)); + llvm::MDNode* reg_info_node = llvm::MDNode::get(*cu->context, reg_info); + inst->setMetadata("RegInfo", reg_info_node); + int promo_size = cu->num_dalvik_registers + cu->num_compiler_temps + 1; + llvm::SmallVector<llvm::Value*, 50> pmap; + for (int i = 0; i < promo_size; i++) { + PromotionMap* p = &cu->promotion_map[i]; + int32_t map_data = ((p->first_in_pair & 0xff) << 24) | + ((p->FpReg & 0xff) << 16) | + ((p->core_reg & 0xff) << 8) | + ((p->fp_location & 0xf) << 4) | + (p->core_location & 0xf); + pmap.push_back(cu->irb->getInt32(map_data)); + } + llvm::MDNode* map_node = llvm::MDNode::get(*cu->context, pmap); + inst->setMetadata("PromotionMap", map_node); + SetDexOffset(cu, cu->current_dalvik_offset); +} + +static void HandlePhiNodes(CompilationUnit* cu, BasicBlock* bb, llvm::BasicBlock* llvm_bb) +{ + SetDexOffset(cu, bb->start_offset); + for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) { + int opcode = mir->dalvikInsn.opcode; + if (opcode < kMirOpFirst) { + // Stop after first non-pseudo MIR op. + continue; + } + if (opcode != kMirOpPhi) { + // Skip other mir Pseudos. + continue; + } + RegLocation rl_dest = cu->reg_location[mir->ssa_rep->defs[0]]; + /* + * The Art compiler's Phi nodes only handle 32-bit operands, + * representing wide values using a matched set of Phi nodes + * for the lower and upper halves. In the llvm world, we only + * want a single Phi for wides. Here we will simply discard + * the Phi node representing the high word. + */ + if (rl_dest.high_word) { + continue; // No Phi node - handled via low word + } + int* incoming = reinterpret_cast<int*>(mir->dalvikInsn.vB); + llvm::Type* phi_type = + LlvmTypeFromLocRec(cu, rl_dest); + llvm::PHINode* phi = cu->irb->CreatePHI(phi_type, mir->ssa_rep->num_uses); + for (int i = 0; i < mir->ssa_rep->num_uses; i++) { + RegLocation loc; + // Don't check width here. + loc = GetRawSrc(cu, mir, i); + DCHECK_EQ(rl_dest.wide, loc.wide); + DCHECK_EQ(rl_dest.wide & rl_dest.high_word, loc.wide & loc.high_word); + DCHECK_EQ(rl_dest.fp, loc.fp); + DCHECK_EQ(rl_dest.core, loc.core); + DCHECK_EQ(rl_dest.ref, loc.ref); + SafeMap<unsigned int, unsigned int>::iterator it; + it = cu->block_id_map.find(incoming[i]); + DCHECK(it != cu->block_id_map.end()); + DCHECK(GetLLVMValue(cu, loc.orig_sreg) != NULL); + DCHECK(GetLLVMBlock(cu, it->second) != NULL); + phi->addIncoming(GetLLVMValue(cu, loc.orig_sreg), + GetLLVMBlock(cu, it->second)); + } + DefineValueOnly(cu, phi, rl_dest.orig_sreg); + } +} + /* Extended MIR instructions like PHI */ static void ConvertExtendedMIR(CompilationUnit* cu, BasicBlock* bb, MIR* mir, llvm::BasicBlock* llvm_bb) @@ -1632,42 +1733,14 @@ static void ConvertExtendedMIR(CompilationUnit* cu, BasicBlock* bb, MIR* mir, switch (static_cast<ExtendedMIROpcode>(mir->dalvikInsn.opcode)) { case kMirOpPhi: { + // The llvm Phi node already emitted - just DefineValue() here. RegLocation rl_dest = cu->reg_location[mir->ssa_rep->defs[0]]; - /* - * The Art compiler's Phi nodes only handle 32-bit operands, - * representing wide values using a matched set of Phi nodes - * for the lower and upper halves. In the llvm world, we only - * want a single Phi for wides. Here we will simply discard - * the Phi node representing the high word. - */ - if (rl_dest.high_word) { - return; // No Phi node - handled via low word + if (!rl_dest.high_word) { + // Only consider low word of pairs. + DCHECK(GetLLVMValue(cu, rl_dest.orig_sreg) != NULL); + llvm::Value* phi = GetLLVMValue(cu, rl_dest.orig_sreg); + if (1) SetVregOnValue(cu, phi, rl_dest.orig_sreg); } - // LLVM requires that all Phi nodes are at the beginning of the block - llvm::IRBuilderBase::InsertPoint ip = cu->irb->saveAndClearIP(); - cu->irb->SetInsertPoint(llvm_bb); - int* incoming = reinterpret_cast<int*>(mir->dalvikInsn.vB); - llvm::Type* phi_type = - LlvmTypeFromLocRec(cu, rl_dest); - llvm::PHINode* phi = cu->irb->CreatePHI(phi_type, mir->ssa_rep->num_uses); - for (int i = 0; i < mir->ssa_rep->num_uses; i++) { - RegLocation loc; - // Don't check width here. - loc = GetRawSrc(cu, mir, i); - DCHECK_EQ(rl_dest.wide, loc.wide); - DCHECK_EQ(rl_dest.wide & rl_dest.high_word, loc.wide & loc.high_word); - DCHECK_EQ(rl_dest.fp, loc.fp); - DCHECK_EQ(rl_dest.core, loc.core); - DCHECK_EQ(rl_dest.ref, loc.ref); - SafeMap<unsigned int, unsigned int>::iterator it; - it = cu->block_id_map.find(incoming[i]); - DCHECK(it != cu->block_id_map.end()); - phi->addIncoming(GetLLVMValue(cu, loc.orig_sreg), - GetLLVMBlock(cu, it->second)); - } - // Now that Phi node is emitted, add definition at old insert point - cu->irb->restoreIP(ip); - DefineValue(cu, phi, rl_dest.orig_sreg); break; } case kMirOpCopy: { @@ -1702,48 +1775,6 @@ static void ConvertExtendedMIR(CompilationUnit* cu, BasicBlock* bb, MIR* mir, } } -static void SetDexOffset(CompilationUnit* cu, int32_t offset) -{ - cu->current_dalvik_offset = offset; - llvm::SmallVector<llvm::Value*, 1> array_ref; - array_ref.push_back(cu->irb->getInt32(offset)); - llvm::MDNode* node = llvm::MDNode::get(*cu->context, array_ref); - cu->irb->SetDexOffset(node); -} - -// Attach method info as metadata to special intrinsic -static void SetMethodInfo(CompilationUnit* cu) -{ - // We don't want dex offset on this - cu->irb->SetDexOffset(NULL); - greenland::IntrinsicHelper::IntrinsicId id; - id = greenland::IntrinsicHelper::MethodInfo; - llvm::Function* intr = cu->intrinsic_helper->GetIntrinsicFunction(id); - llvm::Instruction* inst = cu->irb->CreateCall(intr); - llvm::SmallVector<llvm::Value*, 2> reg_info; - reg_info.push_back(cu->irb->getInt32(cu->num_ins)); - reg_info.push_back(cu->irb->getInt32(cu->num_regs)); - reg_info.push_back(cu->irb->getInt32(cu->num_outs)); - reg_info.push_back(cu->irb->getInt32(cu->num_compiler_temps)); - reg_info.push_back(cu->irb->getInt32(cu->num_ssa_regs)); - llvm::MDNode* reg_info_node = llvm::MDNode::get(*cu->context, reg_info); - inst->setMetadata("RegInfo", reg_info_node); - int promo_size = cu->num_dalvik_registers + cu->num_compiler_temps + 1; - llvm::SmallVector<llvm::Value*, 50> pmap; - for (int i = 0; i < promo_size; i++) { - PromotionMap* p = &cu->promotion_map[i]; - int32_t map_data = ((p->first_in_pair & 0xff) << 24) | - ((p->FpReg & 0xff) << 16) | - ((p->core_reg & 0xff) << 8) | - ((p->fp_location & 0xf) << 4) | - (p->core_location & 0xf); - pmap.push_back(cu->irb->getInt32(map_data)); - } - llvm::MDNode* map_node = llvm::MDNode::get(*cu->context, pmap); - inst->setMetadata("PromotionMap", map_node); - SetDexOffset(cu, cu->current_dalvik_offset); -} - /* Handle the content in each basic block */ static bool BlockBitcodeConversion(CompilationUnit* cu, BasicBlock* bb) { @@ -1811,6 +1842,8 @@ static bool BlockBitcodeConversion(CompilationUnit* cu, BasicBlock* bb) return false; } + HandlePhiNodes(cu, bb, llvm_bb); + for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) { SetDexOffset(cu, mir->offset); diff --git a/src/compiler/frontend.h b/src/compiler/frontend.h index fb32cdd31a..9cf3080ef0 100644 --- a/src/compiler/frontend.h +++ b/src/compiler/frontend.h @@ -145,6 +145,7 @@ extern "C" art::CompiledMethod* ArtCompileMethod(art::Compiler& compiler, const art::DexFile::CodeItem* code_item, uint32_t access_flags, art::InvokeType invoke_type, + uint32_t class_dex_idx, uint32_t method_idx, jobject class_loader, const art::DexFile& dex_file); |