| /* |
| * 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_ |