summaryrefslogtreecommitdiffstats
path: root/compiler/sea_ir
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2013-08-16 22:56:30 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-08-16 22:56:30 +0000
commit3eeda8fe5a481226b246d08e1c645f3ee3b48cf2 (patch)
tree0f96cb7f34888aa81b4dc2ce9345d979987745ec /compiler/sea_ir
parent0e480cad5d2cf0904b98b7b56e90280e9b97ba30 (diff)
parent90af14d2743614e3e1453984b14258a6f145501d (diff)
downloadart-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.cc58
-rw-r--r--compiler/sea_ir/code_gen/code_gen.h16
-rw-r--r--compiler/sea_ir/code_gen/code_gen_data.cc104
-rw-r--r--compiler/sea_ir/debug/dot_gen.h4
-rw-r--r--compiler/sea_ir/frontend.cc25
-rw-r--r--compiler/sea_ir/ir/instruction_nodes.h12
-rw-r--r--compiler/sea_ir/ir/sea.cc42
-rw-r--r--compiler/sea_ir/ir/sea.h17
-rw-r--r--compiler/sea_ir/types/type_inference.cc15
-rw-r--r--compiler/sea_ir/types/type_inference.h9
-rw-r--r--compiler/sea_ir/types/type_inference_visitor.cc6
-rw-r--r--compiler/sea_ir/types/type_inference_visitor.h2
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);