Add Dalvik register allocation codegen.
Change-Id: I8842b1b03ff3fa362b69d386cc5927be6d65b460
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 0ceca0d..31e3c07 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -29,6 +29,7 @@
#include <iomanip>
#include <llvm/Analysis/Verifier.h>
+#include <llvm/BasicBlock.h>
#include <llvm/Function.h>
namespace art {
@@ -52,12 +53,14 @@
method_helper_(method_), method_idx_(method_idx),
access_flags_(access_flags), module_(compiler_llvm_->GetModule()),
context_(compiler_llvm_->GetLLVMContext()),
- irb_(*compiler_llvm_->GetIRBuilder()), func_(NULL),
- prologue_(NULL), basic_blocks_(code_item->insns_size_in_code_units_) {
+ irb_(*compiler_llvm_->GetIRBuilder()), func_(NULL), retval_reg_(NULL),
+ basic_block_reg_alloca_(NULL), basic_block_reg_zero_init_(NULL),
+ basic_blocks_(code_item->insns_size_in_code_units_) {
}
MethodCompiler::~MethodCompiler() {
+ STLDeleteElements(®s_);
}
@@ -123,7 +126,28 @@
void MethodCompiler::EmitPrologue() {
- // UNIMPLEMENTED(WARNING);
+ // Create basic blocks for prologue
+ basic_block_reg_alloca_ =
+ llvm::BasicBlock::Create(*context_, "prologue.alloca", func_);
+
+ basic_block_reg_zero_init_ =
+ llvm::BasicBlock::Create(*context_, "prologue.zeroinit", func_);
+
+ // Create register array
+ for (uint16_t r = 0; r < code_item_->registers_size_; ++r) {
+ regs_.push_back(DalvikReg::CreateLocalVarReg(*this, r));
+ }
+
+ retval_reg_.reset(DalvikReg::CreateRetValReg(*this));
+}
+
+
+void MethodCompiler::EmitPrologueLastBranch() {
+ irb_.SetInsertPoint(basic_block_reg_alloca_);
+ irb_.CreateBr(basic_block_reg_zero_init_);
+
+ irb_.SetInsertPoint(basic_block_reg_zero_init_);
+ irb_.CreateBr(GetBasicBlock(0));
}
@@ -154,6 +178,7 @@
EmitPrologue();
EmitInstructions();
+ EmitPrologueLastBranch();
// Verify the generated bitcode
llvm::verifyFunction(*func_, llvm::PrintMessageAction);
@@ -205,5 +230,89 @@
}
+llvm::Value* MethodCompiler::AllocDalvikLocalVarReg(RegCategory cat,
+ uint32_t reg_idx) {
+
+ // Save current IR builder insert point
+ llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
+
+ // Alloca
+ llvm::Value* reg_addr = NULL;
+
+ switch (cat) {
+ case kRegCat1nr:
+ irb_.SetInsertPoint(basic_block_reg_alloca_);
+ reg_addr = irb_.CreateAlloca(irb_.getJIntTy(), 0,
+ StringPrintf("r%u", reg_idx));
+
+ irb_.SetInsertPoint(basic_block_reg_zero_init_);
+ irb_.CreateStore(irb_.getJInt(0), reg_addr);
+ break;
+
+ case kRegCat2:
+ irb_.SetInsertPoint(basic_block_reg_alloca_);
+ reg_addr = irb_.CreateAlloca(irb_.getJLongTy(), 0,
+ StringPrintf("w%u", reg_idx));
+
+ irb_.SetInsertPoint(basic_block_reg_zero_init_);
+ irb_.CreateStore(irb_.getJLong(0), reg_addr);
+ break;
+
+ case kRegObject:
+ irb_.SetInsertPoint(basic_block_reg_alloca_);
+ reg_addr = irb_.CreateAlloca(irb_.getJObjectTy(), 0,
+ StringPrintf("p%u", reg_idx));
+
+ irb_.SetInsertPoint(basic_block_reg_zero_init_);
+ irb_.CreateStore(irb_.getJNull(), reg_addr);
+ break;
+
+ default:
+ LOG(FATAL) << "Unknown register category for allocation: " << cat;
+ }
+
+ // Restore IRBuilder insert point
+ irb_.restoreIP(irb_ip_original);
+
+ DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
+ return reg_addr;
+}
+
+
+llvm::Value* MethodCompiler::AllocDalvikRetValReg(RegCategory cat) {
+ // Save current IR builder insert point
+ llvm::IRBuilderBase::InsertPoint irb_ip_original = irb_.saveIP();
+
+ // Alloca
+ llvm::Value* reg_addr = NULL;
+
+ switch (cat) {
+ case kRegCat1nr:
+ irb_.SetInsertPoint(basic_block_reg_alloca_);
+ reg_addr = irb_.CreateAlloca(irb_.getJIntTy(), 0, "r_res");
+ break;
+
+ case kRegCat2:
+ irb_.SetInsertPoint(basic_block_reg_alloca_);
+ reg_addr = irb_.CreateAlloca(irb_.getJLongTy(), 0, "w_res");
+ break;
+
+ case kRegObject:
+ irb_.SetInsertPoint(basic_block_reg_alloca_);
+ reg_addr = irb_.CreateAlloca(irb_.getJObjectTy(), 0, "p_res");
+ break;
+
+ default:
+ LOG(FATAL) << "Unknown register category for allocation: " << cat;
+ }
+
+ // Restore IRBuilder insert point
+ irb_.restoreIP(irb_ip_original);
+
+ DCHECK_NE(reg_addr, static_cast<llvm::Value*>(NULL));
+ return reg_addr;
+}
+
+
} // namespace compiler_llvm
} // namespace art