diff options
author | Ian Rogers <irogers@google.com> | 2013-08-16 22:56:30 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-08-16 22:56:30 +0000 |
commit | 3eeda8fe5a481226b246d08e1c645f3ee3b48cf2 (patch) | |
tree | 0f96cb7f34888aa81b4dc2ce9345d979987745ec /compiler/sea_ir | |
parent | 0e480cad5d2cf0904b98b7b56e90280e9b97ba30 (diff) | |
parent | 90af14d2743614e3e1453984b14258a6f145501d (diff) | |
download | art-3eeda8fe5a481226b246d08e1c645f3ee3b48cf2.zip art-3eeda8fe5a481226b246d08e1c645f3ee3b48cf2.tar.gz art-3eeda8fe5a481226b246d08e1c645f3ee3b48cf2.tar.bz2 |
Merge "Get SEA fibonacci running in interpreter mode." into dalvik-dev
Diffstat (limited to 'compiler/sea_ir')
-rw-r--r-- | compiler/sea_ir/code_gen/code_gen.cc | 58 | ||||
-rw-r--r-- | compiler/sea_ir/code_gen/code_gen.h | 16 | ||||
-rw-r--r-- | compiler/sea_ir/code_gen/code_gen_data.cc | 104 | ||||
-rw-r--r-- | compiler/sea_ir/debug/dot_gen.h | 4 | ||||
-rw-r--r-- | compiler/sea_ir/frontend.cc | 25 | ||||
-rw-r--r-- | compiler/sea_ir/ir/instruction_nodes.h | 12 | ||||
-rw-r--r-- | compiler/sea_ir/ir/sea.cc | 42 | ||||
-rw-r--r-- | compiler/sea_ir/ir/sea.h | 17 | ||||
-rw-r--r-- | compiler/sea_ir/types/type_inference.cc | 15 | ||||
-rw-r--r-- | compiler/sea_ir/types/type_inference.h | 9 | ||||
-rw-r--r-- | compiler/sea_ir/types/type_inference_visitor.cc | 6 | ||||
-rw-r--r-- | compiler/sea_ir/types/type_inference_visitor.h | 2 |
12 files changed, 225 insertions, 85 deletions
diff --git a/compiler/sea_ir/code_gen/code_gen.cc b/compiler/sea_ir/code_gen/code_gen.cc index cb150e5..8d79c41 100644 --- a/compiler/sea_ir/code_gen/code_gen.cc +++ b/compiler/sea_ir/code_gen/code_gen.cc @@ -15,8 +15,14 @@ */ #include <llvm/Support/raw_ostream.h> + +#include "base/logging.h" +#include "utils.h" + #include "sea_ir/ir/sea.h" #include "sea_ir/code_gen/code_gen.h" +#include "sea_ir/types/type_inference.h" +#include "sea_ir/types/types.h" namespace sea_ir { @@ -50,34 +56,36 @@ void CodeGenPassVisitor::Initialize(SeaGraph* graph) { } } -void CodeGenPostpassVisitor::Visit(SeaGraph* graph) { - std::vector<SignatureNode*>* parameters = graph->GetParameterNodes(); - std::cout << "=== SeaGraph ===" << parameters->size() << std::endl; -} -void CodeGenVisitor::Visit(SeaGraph* graph) { - std::vector<SignatureNode*>* parameters = graph->GetParameterNodes(); - std::cout << "=== SeaGraph ===" << parameters->size() << std::endl; -} +void CodeGenPostpassVisitor::Visit(SeaGraph* graph) { } +void CodeGenVisitor::Visit(SeaGraph* graph) { } void CodeGenPrepassVisitor::Visit(SeaGraph* graph) { std::vector<SignatureNode*>* parameters = graph->GetParameterNodes(); - std::cout << "=== SeaGraph ===" << parameters->size() << std::endl; - // TODO: Extract correct types from dex for params and return value. + // TODO: It may be better to extract correct types from dex + // instead than from type inference. DCHECK(parameters != NULL); - std::vector<llvm::Type*> parameter_types(parameters->size(), - llvm::Type::getInt32Ty(*llvm_data_->context_)); - // Build llvm function name. - std::string function_name = art::StringPrintf( - "class=%d_method=%d", graph->class_def_idx_, graph->method_idx_); + std::vector<llvm::Type*> parameter_types; + for (std::vector<SignatureNode*>::const_iterator param_iterator = parameters->begin(); + param_iterator!= parameters->end(); param_iterator++) { + const Type* param_type = graph->ti_->type_data_.FindTypeOf((*param_iterator)->Id()); + DCHECK(param_type->Equals(graph->ti_->type_cache_->Integer())) + << "Code generation for types other than integer not implemented."; + parameter_types.push_back(llvm::Type::getInt32Ty(*llvm_data_->context_)); + } - // Build llvm function type and parameters. + // TODO: Get correct function return type. + const Type* return_type = graph->ti_->type_data_.FindTypeOf(-1); + DCHECK(return_type->Equals(graph->ti_->type_cache_->Integer())) + << "Code generation for types other than integer not implemented."; llvm::FunctionType *function_type = llvm::FunctionType::get( llvm::Type::getInt32Ty(*llvm_data_->context_), parameter_types, false); + llvm_data_->function_ = llvm::Function::Create(function_type, - llvm::Function::ExternalLinkage, function_name, &llvm_data_->module_); + llvm::Function::ExternalLinkage, function_name_, &llvm_data_->module_); unsigned param_id = 0; for (llvm::Function::arg_iterator arg_it = llvm_data_->function_->arg_begin(); param_id != llvm_data_->function_->arg_size(); ++arg_it, ++param_id) { + // TODO: The "+1" is because of the Method parameter on position 0. DCHECK(parameters->size() > param_id) << "Insufficient parameters for function signature"; // Build parameter register name for LLVM IR clarity. std::string arg_name = art::StringPrintf("r%d", parameters->at(param_id)->GetResultRegister()); @@ -97,15 +105,12 @@ void CodeGenPrepassVisitor::Visit(SeaGraph* graph) { } void CodeGenPrepassVisitor::Visit(Region* region) { - std::cout << " == Region " << region->StringId() << " ==" << std::endl; llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region)); } void CodeGenPostpassVisitor::Visit(Region* region) { - std::cout << " == Region " << region->StringId() << " ==" << std::endl; llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region)); } void CodeGenVisitor::Visit(Region* region) { - std::cout << " == Region " << region->StringId() << " ==" << std::endl; llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region)); } @@ -189,13 +194,17 @@ void CodeGenVisitor::Visit(MoveResultInstructionNode* instruction) { void CodeGenVisitor::Visit(InvokeStaticInstructionNode* invoke) { std::string instr = invoke->GetInstruction()->DumpString(NULL); std::cout << "6.Instruction: " << instr << std::endl; - // TODO: Build callee llvm function name. - std::string function_name = art::StringPrintf("class=%d_method=%d", 0, 1); + // TODO: Build callee LLVM function name. + std::string symbol = "dex_"; + symbol += art::MangleForJni(PrettyMethod(invoke->GetCalledMethodIndex(), dex_file_)); + std::string function_name = "dex_int_00020Main_fibonacci_00028int_00029"; llvm::Function *callee = llvm_data_->module_.getFunction(function_name); // TODO: Add proper checking of the matching between formal and actual signature. DCHECK(NULL != callee); std::vector<llvm::Value*> parameter_values; std::vector<InstructionNode*> parameter_sources = invoke->GetSSAProducers(); + // TODO: Replace first parameter with Method argument instead of 0. + parameter_values.push_back(llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, 0))); for (std::vector<InstructionNode*>::const_iterator cit = parameter_sources.begin(); cit != parameter_sources.end(); ++cit) { llvm::Value* parameter_value = llvm_data_->GetValue((*cit)); @@ -245,7 +254,7 @@ void CodeGenVisitor::Visit(IfEqzInstructionNode* instruction) { } void CodeGenPostpassVisitor::Visit(PhiInstructionNode* phi) { - std::cout << "Phi node for: " << phi->GetRegisterNumber() << std::endl; + std::cout << "10. Instruction: Phi(" << phi->GetRegisterNumber() << ")" << std::endl; Region* r = phi->GetRegion(); const std::vector<Region*>* predecessors = r->GetPredecessors(); DCHECK(NULL != predecessors); @@ -267,17 +276,14 @@ void CodeGenPostpassVisitor::Visit(PhiInstructionNode* phi) { } void CodeGenVisitor::Visit(SignatureNode* signature) { - std::cout << "Signature: ;" << "Id:" << signature->StringId() << std::endl; DCHECK_EQ(signature->GetDefinitions().size(), 1u) << "Signature nodes must correspond to a single parameter register."; } void CodeGenPrepassVisitor::Visit(SignatureNode* signature) { - std::cout << "Signature: ;" << "Id:" << signature->StringId() << std::endl; DCHECK_EQ(signature->GetDefinitions().size(), 1u) << "Signature nodes must correspond to a single parameter register."; } void CodeGenPostpassVisitor::Visit(SignatureNode* signature) { - std::cout << "Signature: ;" << "Id:" << signature->StringId() << std::endl; DCHECK_EQ(signature->GetDefinitions().size(), 1u) << "Signature nodes must correspond to a single parameter register."; } diff --git a/compiler/sea_ir/code_gen/code_gen.h b/compiler/sea_ir/code_gen/code_gen.h index b1bc4dc..544e9f0 100644 --- a/compiler/sea_ir/code_gen/code_gen.h +++ b/compiler/sea_ir/code_gen/code_gen.h @@ -17,6 +17,7 @@ #ifndef ART_COMPILER_SEA_IR_CODE_GEN_CODE_GEN_H_ #define ART_COMPILER_SEA_IR_CODE_GEN_CODE_GEN_H_ +#include "instruction_set.h" #include "llvm/Analysis/Verifier.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" @@ -66,6 +67,9 @@ class CodeGenData { void AddValue(InstructionNode* instruction, llvm::Value* value) { AddValue(instruction->Id(), value); } + // Generates and returns in @elf the executable code corresponding to the llvm module + // + std::string GetElf(art::InstructionSet instruction_set); llvm::LLVMContext* const context_; llvm::Module module_; @@ -97,6 +101,8 @@ class CodeGenPassVisitor: public IRVisitor { class CodeGenPrepassVisitor: public CodeGenPassVisitor { public: + explicit CodeGenPrepassVisitor(const std::string& function_name): + function_name_(function_name) { } void Visit(SeaGraph* graph); void Visit(SignatureNode* region); void Visit(Region* region); @@ -113,6 +119,9 @@ class CodeGenPrepassVisitor: public CodeGenPassVisitor { void Visit(GotoInstructionNode* instruction) { } void Visit(IfEqzInstructionNode* instruction) { } void Visit(PhiInstructionNode* region); + + private: + std::string function_name_; }; class CodeGenPostpassVisitor: public CodeGenPassVisitor { @@ -137,7 +146,8 @@ class CodeGenPostpassVisitor: public CodeGenPassVisitor { class CodeGenVisitor: public CodeGenPassVisitor { public: - explicit CodeGenVisitor(CodeGenData* code_gen_data): CodeGenPassVisitor(code_gen_data) { } + explicit CodeGenVisitor(CodeGenData* code_gen_data, + const art::DexFile& dex_file): CodeGenPassVisitor(code_gen_data), dex_file_(dex_file) { } void Visit(SeaGraph* graph); void Visit(SignatureNode* region); void Visit(Region* region); @@ -152,6 +162,10 @@ class CodeGenVisitor: public CodeGenPassVisitor { void Visit(GotoInstructionNode* instruction); void Visit(IfEqzInstructionNode* instruction); void Visit(PhiInstructionNode* region) { } + + private: + std::string function_name_; + const art::DexFile& dex_file_; }; } // namespace sea_ir #endif // ART_COMPILER_SEA_IR_CODE_GEN_CODE_GEN_H_ diff --git a/compiler/sea_ir/code_gen/code_gen_data.cc b/compiler/sea_ir/code_gen/code_gen_data.cc new file mode 100644 index 0000000..3baaa99 --- /dev/null +++ b/compiler/sea_ir/code_gen/code_gen_data.cc @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <string> +#include <llvm/PassManager.h> +#include <llvm/Support/TargetRegistry.h> +#include <llvm/Support/FormattedStream.h> +#include <llvm/Target/TargetMachine.h> +#include <llvm/Transforms/IPO.h> +#include <llvm/Transforms/IPO/PassManagerBuilder.h> + +#include "base/logging.h" +#include "driver/compiler_driver.h" +#include "sea_ir/ir/sea.h" +#include "sea_ir/code_gen/code_gen.h" + + +namespace sea_ir { +std::string CodeGenData::GetElf(art::InstructionSet instruction_set) { + std::string elf; + ::llvm::raw_string_ostream out_stream(elf); + // Lookup the LLVM target + std::string target_triple; + std::string target_cpu; + std::string target_attr; + art::CompilerDriver::InstructionSetToLLVMTarget(instruction_set, + target_triple, target_cpu, target_attr); + + std::string errmsg; + const ::llvm::Target* target = + ::llvm::TargetRegistry::lookupTarget(target_triple, errmsg); + + CHECK(target != NULL) << errmsg; + + // Target options + ::llvm::TargetOptions target_options; + target_options.FloatABIType = ::llvm::FloatABI::Soft; + target_options.NoFramePointerElim = true; + target_options.NoFramePointerElimNonLeaf = true; + target_options.UseSoftFloat = false; + target_options.EnableFastISel = false; + + // Create the ::llvm::TargetMachine + ::llvm::OwningPtr< ::llvm::TargetMachine> target_machine( + target->createTargetMachine(target_triple, target_cpu, target_attr, target_options, + ::llvm::Reloc::Static, ::llvm::CodeModel::Small, + ::llvm::CodeGenOpt::Aggressive)); + + CHECK(target_machine.get() != NULL) << "Failed to create target machine"; + + // Add target data + const ::llvm::DataLayout* data_layout = target_machine->getDataLayout(); + + // PassManager for code generation passes + ::llvm::PassManager pm; + pm.add(new ::llvm::DataLayout(*data_layout)); + + // FunctionPassManager for optimization pass + ::llvm::FunctionPassManager fpm(&module_); + fpm.add(new ::llvm::DataLayout(*data_layout)); + + // Add optimization pass + ::llvm::PassManagerBuilder pm_builder; + // TODO: Use inliner after we can do IPO. + pm_builder.Inliner = NULL; + // pm_builder.Inliner = ::llvm::createFunctionInliningPass(); + // pm_builder.Inliner = ::llvm::createAlwaysInlinerPass(); + // pm_builder.Inliner = ::llvm::createPartialInliningPass(); + pm_builder.OptLevel = 3; + pm_builder.DisableSimplifyLibCalls = 1; + pm_builder.DisableUnitAtATime = 1; + pm_builder.populateFunctionPassManager(fpm); + pm_builder.populateModulePassManager(pm); + pm.add(::llvm::createStripDeadPrototypesPass()); + // Add passes to emit ELF image + { + ::llvm::formatted_raw_ostream formatted_os(out_stream, false); + // Ask the target to add backend passes as necessary. + if (target_machine->addPassesToEmitFile(pm, + formatted_os, + ::llvm::TargetMachine::CGFT_ObjectFile, + true)) { + LOG(FATAL) << "Unable to generate ELF for this target"; + } + + // Run the code generation passes + pm.run(module_); + } + return elf; +} +} diff --git a/compiler/sea_ir/debug/dot_gen.h b/compiler/sea_ir/debug/dot_gen.h index 05d97fa..f2ab8c4 100644 --- a/compiler/sea_ir/debug/dot_gen.h +++ b/compiler/sea_ir/debug/dot_gen.h @@ -101,10 +101,10 @@ class DotConversion { // Saves to @filename the .dot representation of @graph with the options @options. void DumpSea(SeaGraph* graph, std::string filename, art::SafeMap<int, const Type*>* types) const { - LOG(INFO) << "Starting to write SEA string to file."; + LOG(INFO) << "Starting to write SEA string to file " << filename << std::endl; DotGenerationVisitor dgv = DotGenerationVisitor(&options_, types); graph->Accept(&dgv); - art::File* file = art::OS::OpenFileReadWrite(filename.c_str()); + art::File* file = art::OS::CreateEmptyFile(filename.c_str()); art::FileOutputStream fos(file); std::string graph_as_string = dgv.GetResult(); graph_as_string += "}"; diff --git a/compiler/sea_ir/frontend.cc b/compiler/sea_ir/frontend.cc index 421c3a4..6efc103 100644 --- a/compiler/sea_ir/frontend.cc +++ b/compiler/sea_ir/frontend.cc @@ -35,7 +35,6 @@ #include "sea_ir/types/types.h" #include "sea_ir/code_gen/code_gen.h" - namespace art { static CompiledMethod* CompileMethodWithSeaIr(CompilerDriver& compiler, @@ -48,34 +47,22 @@ static CompiledMethod* CompileMethodWithSeaIr(CompilerDriver& compiler, , llvm::LlvmCompilationUnit* llvm_compilation_unit #endif ) { - // NOTE: Instead of keeping the convention from the Dalvik frontend.cc - // and silencing the cpplint.py warning, I just corrected the formatting. - VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "..."; + LOG(INFO) << "Compiling " << PrettyMethod(method_idx, dex_file) << "."; sea_ir::SeaGraph* ir_graph = sea_ir::SeaGraph::GetGraph(dex_file); - sea_ir::CodeGenData* llvm_data = - ir_graph->CompileMethod(code_item, class_def_idx, method_idx, method_access_flags, dex_file); + std::string symbol = "dex_" + MangleForJni(PrettyMethod(method_idx, dex_file)); + sea_ir::CodeGenData* llvm_data = ir_graph->CompileMethod(symbol, + code_item, class_def_idx, method_idx, method_access_flags, dex_file); sea_ir::DotConversion dc; SafeMap<int, const sea_ir::Type*>* types = ir_graph->ti_->GetTypeMap(); dc.DumpSea(ir_graph, "/tmp/temp.dot", types); - CHECK(0 && "No SEA compiled function exists yet."); - MethodReference mref(&dex_file, method_idx); - - // TODO: Passing the LLVM code as string is ugly and inefficient, - // but it is the way portable did it. I kept it for compatibility, - // but actually it should not happen. - std::string llvm_code; - ::llvm::raw_string_ostream str_os(llvm_code); - ::llvm::WriteBitcodeToFile(&llvm_data->module_, str_os); - - std::string symbol = "dex_"; - symbol += MangleForJni(PrettyMethod(method_idx, dex_file)); - + std::string llvm_code = llvm_data->GetElf(compiler.GetInstructionSet()); CompiledMethod* compiled_method = new CompiledMethod( compiler.GetInstructionSet(), llvm_code, *verifier::MethodVerifier::GetDexGcMap(mref), symbol); + LOG(INFO) << "Compiled SEA IR method " << PrettyMethod(method_idx, dex_file) << "."; return compiled_method; } diff --git a/compiler/sea_ir/ir/instruction_nodes.h b/compiler/sea_ir/ir/instruction_nodes.h index 906a10f..63e89e7 100644 --- a/compiler/sea_ir/ir/instruction_nodes.h +++ b/compiler/sea_ir/ir/instruction_nodes.h @@ -56,6 +56,8 @@ class InstructionNode: public SeaNode { // essentially creating SSA form. void RenameToSSA(int reg_no, InstructionNode* definition) { definition_edges_.insert(std::pair<int, InstructionNode*>(reg_no, definition)); + DCHECK(NULL != definition) << "SSA definition for register " << reg_no + << " used in instruction " << Id() << " not found."; definition->AddSSAUse(this); } // Returns the ordered set of Instructions that define the input operands of this instruction. @@ -179,14 +181,22 @@ class MoveResultInstructionNode: public InstructionNode { class InvokeStaticInstructionNode: public InstructionNode { public: - explicit InvokeStaticInstructionNode(const art::Instruction* inst): InstructionNode(inst) { } + explicit InvokeStaticInstructionNode(const art::Instruction* inst): InstructionNode(inst), + method_index_(inst->VRegB_35c()) { } int GetResultRegister() const { return RETURN_REGISTER; } + + int GetCalledMethodIndex() const { + return method_index_; + } void Accept(IRVisitor* v) { v->Visit(this); v->Traverse(this); } + + private: + const uint32_t method_index_; }; class AddIntInstructionNode: public InstructionNode { diff --git a/compiler/sea_ir/ir/sea.cc b/compiler/sea_ir/ir/sea.cc index 902839d..5ccaba6 100644 --- a/compiler/sea_ir/ir/sea.cc +++ b/compiler/sea_ir/ir/sea.cc @@ -174,6 +174,21 @@ void SeaGraph::ComputeReachingDefs() { DCHECK(!changed) << "Reaching definitions computation did not reach a fixed point."; } +void SeaGraph::InsertSignatureNodes(const art::DexFile::CodeItem* code_item, Region* r) { + // Insert a fake SignatureNode for the first parameter. + // TODO: Provide a register enum value for the fake parameter. + SignatureNode* parameter_def_node = new sea_ir::SignatureNode(0, 0); + AddParameterNode(parameter_def_node); + r->AddChild(parameter_def_node); + // Insert SignatureNodes for each Dalvik register parameter. + for (unsigned int crt_offset = 0; crt_offset < code_item->ins_size_; crt_offset++) { + int register_no = code_item->registers_size_ - crt_offset - 1; + int position = crt_offset + 1; + SignatureNode* parameter_def_node = new sea_ir::SignatureNode(register_no, position); + AddParameterNode(parameter_def_node); + r->AddChild(parameter_def_node); + } +} void SeaGraph::BuildMethodSeaGraph(const art::DexFile::CodeItem* code_item, const art::DexFile& dex_file, uint32_t class_def_idx, @@ -209,15 +224,8 @@ void SeaGraph::BuildMethodSeaGraph(const art::DexFile::CodeItem* code_item, Region* r = GetNewRegion(); - // Insert one SignatureNode per function argument, - // to serve as placeholder definitions in dataflow analysis. - for (unsigned int crt_offset = 0; crt_offset < code_item->ins_size_; crt_offset++) { - int position = crt_offset; // TODO: Is this the correct offset in the signature? - SignatureNode* parameter_def_node = - new sea_ir::SignatureNode(code_item->registers_size_ - 1 - crt_offset, position); - AddParameterNode(parameter_def_node); - r->AddChild(parameter_def_node); - } + + InsertSignatureNodes(code_item, r); // Pass: Assign instructions to region nodes and // assign branches their control flow successors. i = 0; @@ -386,23 +394,21 @@ void SeaGraph::RenameAsSSA(Region* crt_region, scoped_table->CloseScope(); } -CodeGenData* SeaGraph::GenerateLLVM() { +CodeGenData* SeaGraph::GenerateLLVM(const std::string& function_name, + const art::DexFile& dex_file) { // Pass: Generate LLVM IR. - CodeGenPrepassVisitor code_gen_prepass_visitor; + CodeGenPrepassVisitor code_gen_prepass_visitor(function_name); std::cout << "Generating code..." << std::endl; - std::cout << "=== PRE VISITING ===" << std::endl; Accept(&code_gen_prepass_visitor); - CodeGenVisitor code_gen_visitor(code_gen_prepass_visitor.GetData()); - std::cout << "=== VISITING ===" << std::endl; + CodeGenVisitor code_gen_visitor(code_gen_prepass_visitor.GetData(), dex_file); Accept(&code_gen_visitor); - std::cout << "=== POST VISITING ===" << std::endl; CodeGenPostpassVisitor code_gen_postpass_visitor(code_gen_visitor.GetData()); Accept(&code_gen_postpass_visitor); - code_gen_postpass_visitor.Write(std::string("my_file.llvm")); return code_gen_postpass_visitor.GetData(); } CodeGenData* SeaGraph::CompileMethod( + const std::string& function_name, const art::DexFile::CodeItem* code_item, uint32_t class_def_idx, uint32_t method_idx, uint32_t method_access_flags, const art::DexFile& dex_file) { // Two passes: Builds the intermediate structure (non-SSA) of the sea-ir for the function. @@ -422,7 +428,7 @@ CodeGenData* SeaGraph::CompileMethod( // Pass: type inference ti_->ComputeTypes(this); // Pass: Generate LLVM IR. - CodeGenData* cgd = GenerateLLVM(); + CodeGenData* cgd = GenerateLLVM(function_name, dex_file); return cgd; } @@ -607,7 +613,7 @@ std::vector<InstructionNode*> InstructionNode::Create(const art::Instruction* in sea_instructions.push_back(new IfNeInstructionNode(in)); break; case art::Instruction::ADD_INT_LIT8: - sea_instructions.push_back(new UnnamedConstInstructionNode(in, in->VRegB_22b())); + sea_instructions.push_back(new UnnamedConstInstructionNode(in, in->VRegC_22b())); sea_instructions.push_back(new AddIntLitInstructionNode(in)); break; case art::Instruction::MOVE_RESULT: diff --git a/compiler/sea_ir/ir/sea.h b/compiler/sea_ir/ir/sea.h index df420ed..92c2043 100644 --- a/compiler/sea_ir/ir/sea.h +++ b/compiler/sea_ir/ir/sea.h @@ -50,12 +50,12 @@ class SignatureNode; class SignatureNode: public InstructionNode { public: // Creates a new signature node representing the initial definition of the - // register @parameter_register which is the @position-th argument to the method. - explicit SignatureNode(unsigned int parameter_register, unsigned int position): - InstructionNode(NULL), parameter_register_(parameter_register), position_(position) { } + // register @register_no which is the @signature_position-th argument to the method. + explicit SignatureNode(unsigned int register_no, unsigned int signature_position): + InstructionNode(NULL), register_no_(register_no), position_(signature_position) { } int GetResultRegister() const { - return parameter_register_; + return register_no_; } unsigned int GetPositionInSignature() const { @@ -72,7 +72,7 @@ class SignatureNode: public InstructionNode { } private: - const unsigned int parameter_register_; + const unsigned int register_no_; const unsigned int position_; // The position of this parameter node is // in the function parameter list. }; @@ -261,7 +261,8 @@ class SeaGraph: IVisitable { public: static SeaGraph* GetGraph(const art::DexFile&); - CodeGenData* CompileMethod(const art::DexFile::CodeItem* code_item, uint32_t class_def_idx, + CodeGenData* CompileMethod(const std::string& function_name, + const art::DexFile::CodeItem* code_item, uint32_t class_def_idx, uint32_t method_idx, uint32_t method_access_flags, const art::DexFile& dex_file); // Returns all regions corresponding to this SeaGraph. std::vector<Region*>* GetRegions() { @@ -338,7 +339,9 @@ class SeaGraph: IVisitable { void RenameAsSSA(Region* node, utils::ScopedHashtable<int, InstructionNode*>* scoped_table); // Generate LLVM IR for the method. // Precondition: ConvertToSSA(). - CodeGenData* GenerateLLVM(); + CodeGenData* GenerateLLVM(const std::string& function_name, const art::DexFile& dex_file); + // Inserts one SignatureNode for each argument of the function in + void InsertSignatureNodes(const art::DexFile::CodeItem* code_item, Region* r); static SeaGraph graph_; std::vector<Region*> regions_; diff --git a/compiler/sea_ir/types/type_inference.cc b/compiler/sea_ir/types/type_inference.cc index 31d7f0f..1731987 100644 --- a/compiler/sea_ir/types/type_inference.cc +++ b/compiler/sea_ir/types/type_inference.cc @@ -68,6 +68,9 @@ const Type* FunctionTypeInfo::GetReturnValueType() { std::vector<const Type*> FunctionTypeInfo::GetDeclaredArgumentTypes() { art::ScopedObjectAccess soa(art::Thread::Current()); std::vector<const Type*> argument_types; + // TODO: The additional (fake) Method parameter is added on the first position, + // but is represented as integer because we don't support pointers yet. + argument_types.push_back(&(type_cache_->Integer())); // Include the "this" pointer. size_t cur_arg = 0; if (!IsStatic()) { @@ -82,7 +85,7 @@ std::vector<const Type*> FunctionTypeInfo::GetDeclaredArgumentTypes() { } cur_arg++; } - + // Include the types of the parameters in the Java method signature. const art::DexFile::ProtoId& proto_id = dex_file_->GetMethodPrototype(dex_file_->GetMethodId(dex_method_idx_)); art::DexFileParameterIterator iterator(*dex_file_, proto_id); @@ -149,6 +152,13 @@ void TypeInference::ComputeTypes(SeaGraph* graph) SHARED_LOCKS_REQUIRED(Locks::m std::copy(instructions->begin(), instructions->end(), std::back_inserter(worklist)); } TypeInferenceVisitor tiv(graph, &type_data_, type_cache_); + // Record return type of the function. + graph->Accept(&tiv); + const Type* new_type = tiv.GetType(); + type_data_.SetTypeOf(-1, new_type); // TODO: Record this info in a way that + // does not need magic constants. + // Make SeaGraph a SeaNode? + // Sparse (SSA) fixed-point algorithm that processes each instruction in the work-list, // adding consumers of instructions whose result changed type back into the work-list. // Note: According to [1] list iterators should not be invalidated on insertion, @@ -159,14 +169,11 @@ void TypeInference::ComputeTypes(SeaGraph* graph) SHARED_LOCKS_REQUIRED(Locks::m // TODO: Remove elements as I go. for (std::list<InstructionNode*>::const_iterator instruction_it = worklist.begin(); instruction_it != worklist.end(); instruction_it++) { - std::cout << "[TI] Instruction: " << (*instruction_it)->Id() << std::endl; (*instruction_it)->Accept(&tiv); const Type* old_type = type_data_.FindTypeOf((*instruction_it)->Id()); const Type* new_type = tiv.GetType(); bool type_changed = (old_type != new_type); if (type_changed) { - std::cout << " New type:" << new_type->IsIntegralTypes() << std::endl; - std::cout << " Descrip:" << new_type->Dump()<< " on " << (*instruction_it)->Id() << std::endl; type_data_.SetTypeOf((*instruction_it)->Id(), new_type); // Add SSA consumers of the current instruction to the work-list. std::vector<InstructionNode*>* consumers = (*instruction_it)->GetSSAConsumers(); diff --git a/compiler/sea_ir/types/type_inference.h b/compiler/sea_ir/types/type_inference.h index d951d82..7a178b2 100644 --- a/compiler/sea_ir/types/type_inference.h +++ b/compiler/sea_ir/types/type_inference.h @@ -31,8 +31,7 @@ class InstructionNode; // precise verification (which is the job of the verifier). class TypeInference { public: - TypeInference() { - type_cache_ = new art::verifier::RegTypeCache(false); + TypeInference() : type_cache_(new art::verifier::RegTypeCache(false)) { } // Computes the types for the method with SEA IR representation provided by @graph. @@ -43,10 +42,8 @@ class TypeInference { } // Returns true if @descriptor corresponds to a primitive type. static bool IsPrimitiveDescriptor(char descriptor); - - protected: - art::verifier::RegTypeCache* type_cache_; - TypeData type_data_; + TypeData type_data_; // TODO: Make private, add accessor and not publish a SafeMap above. + art::verifier::RegTypeCache* const type_cache_; // TODO: Make private. }; // Stores information about the exact type of a function. diff --git a/compiler/sea_ir/types/type_inference_visitor.cc b/compiler/sea_ir/types/type_inference_visitor.cc index 81a8f4d..27bb5d8 100644 --- a/compiler/sea_ir/types/type_inference_visitor.cc +++ b/compiler/sea_ir/types/type_inference_visitor.cc @@ -21,6 +21,12 @@ namespace sea_ir { +void TypeInferenceVisitor::Visit(SeaGraph* graph) { + FunctionTypeInfo fti(graph_, type_cache_); + const Type* return_type = fti.GetReturnValueType(); + crt_type_.push_back(return_type); +} + void TypeInferenceVisitor::Visit(SignatureNode* parameter) { FunctionTypeInfo fti(graph_, type_cache_); std::vector<const Type*> arguments = fti.GetDeclaredArgumentTypes(); diff --git a/compiler/sea_ir/types/type_inference_visitor.h b/compiler/sea_ir/types/type_inference_visitor.h index 4bdac38..d715151 100644 --- a/compiler/sea_ir/types/type_inference_visitor.h +++ b/compiler/sea_ir/types/type_inference_visitor.h @@ -40,7 +40,7 @@ class TypeInferenceVisitor: public IRVisitor { } // There are no type related actions to be performed on these classes. void Initialize(SeaGraph* graph) { } - void Visit(SeaGraph* graph) { } + void Visit(SeaGraph* graph); void Visit(Region* region) { } void Visit(PhiInstructionNode* instruction); |