diff options
| -rw-r--r-- | build/Android.libart-compiler-llvm.mk | 4 | ||||
| -rw-r--r-- | build/Android.libart.mk | 2 | ||||
| -rw-r--r-- | src/compiler/codegen/mir_to_gbc.cc | 207 | ||||
| -rw-r--r-- | src/compiler/frontend.h | 1 | ||||
| -rw-r--r-- | src/compiler_llvm/compilation_unit.h | 2 | ||||
| -rw-r--r-- | src/compiler_llvm/compiler_llvm.cc | 19 | ||||
| -rw-r--r-- | src/compiler_llvm/gbc_expander.cc | 8 |
7 files changed, 145 insertions, 98 deletions
diff --git a/build/Android.libart-compiler-llvm.mk b/build/Android.libart-compiler-llvm.mk index daef06e37a..4909f8103d 100644 --- a/build/Android.libart-compiler-llvm.mk +++ b/build/Android.libart-compiler-llvm.mk @@ -15,9 +15,9 @@ # -LIBART_COMPILER_LLVM_CFLAGS := -DART_USE_LLVM_COMPILER +LIBART_COMPILER_LLVM_CFLAGS := -DART_USE_LLVM_COMPILER=1 ifeq ($(ART_USE_PORTABLE_COMPILER),true) - ART_TEST_CFLAGS += -DART_USE_PORTABLE_COMPILER=1 + LIBART_COMPILER_LLVM_CFLAGS += -DART_USE_PORTABLE_COMPILER=1 endif LIBART_COMPILER_LLVM_SRC_FILES += \ diff --git a/build/Android.libart.mk b/build/Android.libart.mk index 435056a1b0..5226db7a10 100644 --- a/build/Android.libart.mk +++ b/build/Android.libart.mk @@ -19,7 +19,7 @@ ifeq ($(ART_USE_LLVM_COMPILER),true) LIBART_CFLAGS += -DART_USE_LLVM_COMPILER=1 endif ifeq ($(ART_USE_PORTABLE_COMPILER),true) - ART_TEST_CFLAGS += -DART_USE_PORTABLE_COMPILER=1 + LIBART_CFLAGS += -DART_USE_PORTABLE_COMPILER=1 endif # $(1): target or host 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); diff --git a/src/compiler_llvm/compilation_unit.h b/src/compiler_llvm/compilation_unit.h index 591d4f0a31..6ebac9aa68 100644 --- a/src/compiler_llvm/compilation_unit.h +++ b/src/compiler_llvm/compilation_unit.h @@ -29,7 +29,7 @@ #include "safe_map.h" #if defined(ART_USE_PORTABLE_COMPILER) -# include "compiler/Dalvik.h" +# include "compiler/compiler_internals.h" # include "compiler.h" # include "oat_compilation_unit.h" #endif diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc index 6de10e6940..29c381d143 100644 --- a/src/compiler_llvm/compiler_llvm.cc +++ b/src/compiler_llvm/compiler_llvm.cc @@ -164,6 +164,18 @@ CompileDexMethod(OatCompilationUnit* oat_compilation_unit, InvokeType invoke_typ return method_compiler->Compile(); } else { + +#if 1 + /* + * FIXME: temporary workaround + * Until Portable/llvm is fixed, use Iceland. + */ + UniquePtr<MethodCompiler> method_compiler( + new MethodCompiler(cunit.get(), compiler_, oat_compilation_unit)); + + return method_compiler->Compile(); +#endif + // TODO: consolidate ArtCompileMethods CompileOneMethod(*compiler_, kPortable, @@ -181,9 +193,10 @@ CompileDexMethod(OatCompilationUnit* oat_compilation_unit, InvokeType invoke_typ cunit->Materialize(); - Compiler::MethodReference mref(dex_file_, method_idx_); - return new CompiledMethod(cunit_->GetInstructionSet(), - cunit_->GetCompiledCode(), + Compiler::MethodReference mref(oat_compilation_unit->GetDexFile(), + oat_compilation_unit->GetDexMethodIndex()); + return new CompiledMethod(compiler_->GetInstructionSet(), + cunit->GetCompiledCode(), *verifier::MethodVerifier::GetDexGcMap(mref)); } #else diff --git a/src/compiler_llvm/gbc_expander.cc b/src/compiler_llvm/gbc_expander.cc index 93d7d48ab3..0f71512e5d 100644 --- a/src/compiler_llvm/gbc_expander.cc +++ b/src/compiler_llvm/gbc_expander.cc @@ -45,7 +45,7 @@ using namespace art::compiler_llvm; using art::greenland::IntrinsicHelper; namespace art { -extern char remapShorty(char shortyType); +extern char RemapShorty(char shortyType); }; namespace { @@ -2485,7 +2485,7 @@ llvm::FunctionType* GBCExpanderPass::GetFunctionType(uint32_t method_idx, char ret_shorty = shorty[0]; #if defined(ART_USE_PORTABLE_COMPILER) - ret_shorty = art::remapShorty(ret_shorty); + ret_shorty = art::RemapShorty(ret_shorty); #endif llvm::Type* ret_type = irb_.getJType(ret_shorty, kAccurate); @@ -2500,7 +2500,7 @@ llvm::FunctionType* GBCExpanderPass::GetFunctionType(uint32_t method_idx, for (uint32_t i = 1; i < shorty_size; ++i) { #if defined(ART_USE_PORTABLE_COMPILER) - char shorty_type = art::remapShorty(shorty[i]); + char shorty_type = art::RemapShorty(shorty[i]); args_type.push_back(irb_.getJType(shorty_type, kAccurate)); #else args_type.push_back(irb_.getJType(shorty[i], kAccurate)); @@ -2635,7 +2635,7 @@ llvm::BasicBlock* GBCExpanderPass::GetUnwindBasicBlock() { // Emit the code to return default value (zero) for the given return type. char ret_shorty = oat_compilation_unit_->GetShorty()[0]; #if defined(ART_USE_PORTABLE_COMPILER) - ret_shorty = art::remapShorty(ret_shorty); + ret_shorty = art::RemapShorty(ret_shorty); #endif if (ret_shorty == 'V') { irb_.CreateRetVoid(); |