Get SEA fibonacci running in interpreter mode.
Android.mk: Added new file to build.
compile_driver.cc: Moved SE_IR usage test in the block
protected by bool compile, which is enabled by
adding a sepatate test in IsCnadidateForCompilation.
class_linker.cc: Added check in NeedsInterpreter to enable SEA_IR.
art_method-inl.h: DIsabled check in SEA_IR mode.
method_verifier.cc: Added check for SEA_IR mode.
method_verifier.h: Chenged IsCandidateForCompilation signature to
allow testing the function name (for SEA_IR selective
compilation).
dot_gen.h: Updated ART file API usage to altest version.
sea_ir/frontend.cc: Passing function symbol name to CompileMethod.
instruction_Nodes.h: Added accessor for method index for
InvokeStatic IR node.
sea.cc: Added additional IR SignatureNode for function calls (extra
Method parameter). Fixed UnnamedConstant constant value.
sea.h: Passing function_name to GenerateLLVM.
type_inference_visitor.cc: Aded type for first (placeholder) method
parameter.
Change-Id: I295858ea0761a3dffb36f35748d8b93d4919d6a9
diff --git a/compiler/Android.mk b/compiler/Android.mk
index 5caf688..c18462a 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -97,6 +97,7 @@
sea_ir/ir/instruction_tools.cc \
sea_ir/ir/sea.cc \
sea_ir/code_gen/code_gen.cc \
+ sea_ir/code_gen/code_gen_data.cc \
sea_ir/types/type_inference.cc \
sea_ir/types/type_inference_visitor.cc \
sea_ir/debug/dot_gen.cc
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 4659f7b..9d583fd 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -314,7 +314,7 @@
uint32_t method_idx,
jobject class_loader,
const art::DexFile& dex_file);
-
+#ifdef ART_SEA_IR_MODE
extern "C" art::CompiledMethod* SeaIrCompileMethod(art::CompilerDriver& compiler,
const art::DexFile::CodeItem* code_item,
uint32_t access_flags,
@@ -323,7 +323,7 @@
uint32_t method_idx,
jobject class_loader,
const art::DexFile& dex_file);
-
+#endif
extern "C" art::CompiledMethod* ArtLLVMJniCompileMethod(art::CompilerDriver& driver,
uint32_t access_flags, uint32_t method_idx,
const art::DexFile& dex_file);
@@ -2230,16 +2230,15 @@
CHECK(compiled_method != NULL);
} else if ((access_flags & kAccAbstract) != 0) {
} else {
- bool compile = verifier::MethodVerifier::IsCandidateForCompilation(code_item, access_flags);
-#ifdef ART_SEA_IR_MODE
- bool use_sea = Runtime::Current()->IsSeaIRMode();
- use_sea = use_sea && (std::string::npos != PrettyMethod(method_idx, dex_file).find("fibonacci"));
- if (use_sea) compile = true;
-#endif
+ MethodReference method_ref(&dex_file, method_idx);
+ bool compile = verifier::MethodVerifier::IsCandidateForCompilation(method_ref, access_flags);
if (compile) {
CompilerFn compiler = compiler_;
#ifdef ART_SEA_IR_MODE
+ bool use_sea = Runtime::Current()->IsSeaIRMode();
+ use_sea = use_sea &&
+ (std::string::npos != PrettyMethod(method_idx, dex_file).find("fibonacci"));
if (use_sea) {
compiler = sea_ir_compiler_;
LOG(INFO) << "Using SEA IR to compile..." << std::endl;
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 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(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(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 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 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 @@
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 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 @@
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 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 @@
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 @@
// 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 @@
, 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 @@
// 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 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 @@
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 @@
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 @@
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 @@
// 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 @@
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: 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 @@
}
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
// 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 @@
// 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 @@
}
// 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 3da2fc1..139c89b 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 200b9f0..469448f 100644
--- a/compiler/sea_ir/types/type_inference_visitor.h
+++ b/compiler/sea_ir/types/type_inference_visitor.h
@@ -40,7 +40,7 @@
}
// 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);