/*
* 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.
*/
#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"
#include "llvm/IR/Module.h"
#include "llvm/Analysis/Verifier.h"
#include "sea_ir/ir/visitor.h"
namespace sea_ir {
// Abstracts away the containers we use to map SEA IR objects to LLVM IR objects.
class CodeGenData {
public:
explicit CodeGenData(): context_(&llvm::getGlobalContext()), module_("sea_ir", *context_),
builder_(*context_), function_(), blocks_(), values_() { }
// Returns the llvm::BasicBlock* corresponding to the sea_ir::Region with id @region_id.
llvm::BasicBlock* GetBlock(int region_id) {
std::map<int, llvm::BasicBlock*>::iterator block_it = blocks_.find(region_id);
DCHECK(block_it != blocks_.end());
return block_it->second;
}
// Returns the llvm::BasicBlock* corresponding top the sea_ir::Region @region.
llvm::BasicBlock* GetBlock(Region* region) {
return GetBlock(region->Id());
}
// Records @block as corresponding to the sea_ir::Region with id @region_id.
void AddBlock(int region_id, llvm::BasicBlock* block) {
blocks_.insert(std::pair<int, llvm::BasicBlock*>(region_id, block));
}
// Records @block as corresponding to the sea_ir::Region with @region.
void AddBlock(Region* region, llvm::BasicBlock* block) {
AddBlock(region->Id(), block);
}
llvm::Value* GetValue(int instruction_id) {
std::map<int, llvm::Value*>::iterator value_it = values_.find(instruction_id);
DCHECK(value_it != values_.end());
return value_it->second;
}
// Returns the llvm::Value* corresponding to the output of @instruction.
llvm::Value* GetValue(InstructionNode* instruction) {
return GetValue(instruction->Id());
}
// Records @value as corresponding to the sea_ir::InstructionNode with id @instruction_id.
void AddValue(int instruction_id, llvm::Value* value) {
values_.insert(std::pair<int, llvm::Value*>(instruction_id, value));
}
// Records @value as corresponding to the sea_ir::InstructionNode @instruction.
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_;
llvm::IRBuilder<> builder_;
llvm::Function* function_;
private:
std::map<int, llvm::BasicBlock*> blocks_;
std::map<int, llvm::Value*> values_;
};
class CodeGenPassVisitor: public IRVisitor {
public:
explicit CodeGenPassVisitor(CodeGenData* cgd): llvm_data_(cgd) { }
CodeGenPassVisitor(): llvm_data_(new CodeGenData()) { }
// Initialize any data structure needed before the start of visiting.
virtual void Initialize(SeaGraph* graph);
CodeGenData* GetData() {
return llvm_data_;
}
void Write(std::string file) {
llvm_data_->module_.dump();
llvm::verifyFunction(*llvm_data_->function_);
}
protected:
CodeGenData* const llvm_data_;
};
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);
void Visit(InstructionNode* instruction) { }
void Visit(UnnamedConstInstructionNode* instruction) { }
void Visit(ConstInstructionNode* instruction) { }
void Visit(ReturnInstructionNode* instruction) { }
void Visit(IfNeInstructionNode* instruction) { }
// void Visit(AddIntLitInstructionNode* instruction) { }
void Visit(MoveResultInstructionNode* instruction) { }
void Visit(InvokeStaticInstructionNode* instruction) { }
void Visit(AddIntInstructionNode* instruction) { }
void Visit(GotoInstructionNode* instruction) { }
void Visit(IfEqzInstructionNode* instruction) { }
void Visit(PhiInstructionNode* region);
private:
std::string function_name_;
};
class CodeGenPostpassVisitor: public CodeGenPassVisitor {
public:
explicit CodeGenPostpassVisitor(CodeGenData* code_gen_data): CodeGenPassVisitor(code_gen_data) { }
void Visit(SeaGraph* graph);
void Visit(SignatureNode* region);
void Visit(Region* region);
void Visit(InstructionNode* region) { }
void Visit(UnnamedConstInstructionNode* instruction) { }
void Visit(ConstInstructionNode* instruction) { }
void Visit(ReturnInstructionNode* instruction) { }
void Visit(IfNeInstructionNode* instruction) { }
// void Visit(AddIntLitInstructionNode* instruction) { }
void Visit(MoveResultInstructionNode* instruction) { }
void Visit(InvokeStaticInstructionNode* instruction) { }
void Visit(AddIntInstructionNode* instruction) { }
void Visit(GotoInstructionNode* instruction) { }
void Visit(IfEqzInstructionNode* instruction) { }
void Visit(PhiInstructionNode* region);
};
class CodeGenVisitor: public CodeGenPassVisitor {
public:
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);
void Visit(InstructionNode* region);
void Visit(UnnamedConstInstructionNode* instruction);
void Visit(ConstInstructionNode* instruction);
void Visit(ReturnInstructionNode* instruction);
void Visit(IfNeInstructionNode* instruction);
void Visit(MoveResultInstructionNode* instruction);
void Visit(InvokeStaticInstructionNode* instruction);
void Visit(AddIntInstructionNode* instruction);
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_