1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_COMPILER_SEA_IR_CODE_GEN_CODE_GEN_H_
18 #define ART_COMPILER_SEA_IR_CODE_GEN_CODE_GEN_H_
19 
20 #include "instruction_set.h"
21 #include "llvm/Analysis/Verifier.h"
22 #include "llvm/IR/IRBuilder.h"
23 #include "llvm/IR/LLVMContext.h"
24 #include "llvm/IR/Module.h"
25 #include "llvm/Analysis/Verifier.h"
26 #include "sea_ir/ir/visitor.h"
27 
28 namespace sea_ir {
29 // Abstracts away the containers we use to map SEA IR objects to LLVM IR objects.
30 class CodeGenData {
31  public:
CodeGenData()32   explicit CodeGenData(): context_(&llvm::getGlobalContext()), module_("sea_ir", *context_),
33       builder_(*context_), function_(), blocks_(), values_() { }
34   // Returns the llvm::BasicBlock* corresponding to the sea_ir::Region with id @region_id.
GetBlock(int region_id)35   llvm::BasicBlock* GetBlock(int region_id) {
36     std::map<int, llvm::BasicBlock*>::iterator block_it = blocks_.find(region_id);
37     DCHECK(block_it != blocks_.end());
38     return block_it->second;
39   }
40   // Returns the llvm::BasicBlock* corresponding top the sea_ir::Region @region.
GetBlock(Region * region)41   llvm::BasicBlock* GetBlock(Region* region) {
42     return GetBlock(region->Id());
43   }
44   // Records @block as corresponding to the sea_ir::Region with id @region_id.
AddBlock(int region_id,llvm::BasicBlock * block)45   void AddBlock(int region_id, llvm::BasicBlock* block) {
46     blocks_.insert(std::pair<int, llvm::BasicBlock*>(region_id, block));
47   }
48   // Records @block as corresponding to the sea_ir::Region with @region.
AddBlock(Region * region,llvm::BasicBlock * block)49   void AddBlock(Region* region, llvm::BasicBlock* block) {
50     AddBlock(region->Id(), block);
51   }
52 
GetValue(int instruction_id)53   llvm::Value* GetValue(int instruction_id) {
54     std::map<int, llvm::Value*>::iterator value_it = values_.find(instruction_id);
55     DCHECK(value_it != values_.end());
56     return value_it->second;
57   }
58   // Returns the llvm::Value* corresponding to the output of @instruction.
GetValue(InstructionNode * instruction)59   llvm::Value* GetValue(InstructionNode* instruction) {
60     return GetValue(instruction->Id());
61   }
62   // Records @value as corresponding to the sea_ir::InstructionNode with id @instruction_id.
AddValue(int instruction_id,llvm::Value * value)63   void AddValue(int instruction_id, llvm::Value* value) {
64     values_.insert(std::pair<int, llvm::Value*>(instruction_id, value));
65   }
66   // Records @value as corresponding to the sea_ir::InstructionNode  @instruction.
AddValue(InstructionNode * instruction,llvm::Value * value)67   void AddValue(InstructionNode* instruction, llvm::Value* value) {
68       AddValue(instruction->Id(), value);
69   }
70   // Generates and returns in @elf the executable code corresponding to the llvm module
71   //
72   std::string GetElf(art::InstructionSet instruction_set);
73 
74   llvm::LLVMContext* const context_;
75   llvm::Module module_;
76   llvm::IRBuilder<> builder_;
77   llvm::Function* function_;
78 
79  private:
80   std::map<int, llvm::BasicBlock*> blocks_;
81   std::map<int, llvm::Value*> values_;
82 };
83 
84 class CodeGenPassVisitor: public IRVisitor {
85  public:
CodeGenPassVisitor(CodeGenData * cgd)86   explicit CodeGenPassVisitor(CodeGenData* cgd): llvm_data_(cgd) { }
CodeGenPassVisitor()87   CodeGenPassVisitor(): llvm_data_(new CodeGenData()) { }
88   // Initialize any data structure needed before the start of visiting.
89   virtual void Initialize(SeaGraph* graph);
GetData()90   CodeGenData* GetData() {
91     return llvm_data_;
92   }
Write(std::string file)93   void Write(std::string file) {
94       llvm_data_->module_.dump();
95       llvm::verifyFunction(*llvm_data_->function_);
96     }
97 
98  protected:
99   CodeGenData* const llvm_data_;
100 };
101 
102 class CodeGenPrepassVisitor: public CodeGenPassVisitor {
103  public:
CodeGenPrepassVisitor(const std::string & function_name)104   explicit CodeGenPrepassVisitor(const std::string& function_name):
105     function_name_(function_name) { }
106   void Visit(SeaGraph* graph);
107   void Visit(SignatureNode* region);
108   void Visit(Region* region);
Visit(InstructionNode * instruction)109   void Visit(InstructionNode* instruction) { }
110 
Visit(UnnamedConstInstructionNode * instruction)111   void Visit(UnnamedConstInstructionNode* instruction) { }
Visit(ConstInstructionNode * instruction)112   void Visit(ConstInstructionNode* instruction) { }
Visit(ReturnInstructionNode * instruction)113   void Visit(ReturnInstructionNode* instruction) { }
Visit(IfNeInstructionNode * instruction)114   void Visit(IfNeInstructionNode* instruction) { }
115   // void Visit(AddIntLitInstructionNode* instruction) { }
Visit(MoveResultInstructionNode * instruction)116   void Visit(MoveResultInstructionNode* instruction) { }
Visit(InvokeStaticInstructionNode * instruction)117   void Visit(InvokeStaticInstructionNode* instruction) { }
Visit(AddIntInstructionNode * instruction)118   void Visit(AddIntInstructionNode* instruction) { }
Visit(GotoInstructionNode * instruction)119   void Visit(GotoInstructionNode* instruction) { }
Visit(IfEqzInstructionNode * instruction)120   void Visit(IfEqzInstructionNode* instruction) { }
121   void Visit(PhiInstructionNode* region);
122 
123  private:
124   std::string function_name_;
125 };
126 
127 class CodeGenPostpassVisitor: public CodeGenPassVisitor {
128  public:
CodeGenPostpassVisitor(CodeGenData * code_gen_data)129   explicit CodeGenPostpassVisitor(CodeGenData* code_gen_data): CodeGenPassVisitor(code_gen_data) { }
130   void Visit(SeaGraph* graph);
131   void Visit(SignatureNode* region);
132   void Visit(Region* region);
Visit(InstructionNode * region)133   void Visit(InstructionNode* region) { }
Visit(UnnamedConstInstructionNode * instruction)134   void Visit(UnnamedConstInstructionNode* instruction) { }
Visit(ConstInstructionNode * instruction)135   void Visit(ConstInstructionNode* instruction) { }
Visit(ReturnInstructionNode * instruction)136   void Visit(ReturnInstructionNode* instruction) { }
Visit(IfNeInstructionNode * instruction)137   void Visit(IfNeInstructionNode* instruction) { }
138   // void Visit(AddIntLitInstructionNode* instruction) { }
Visit(MoveResultInstructionNode * instruction)139   void Visit(MoveResultInstructionNode* instruction) { }
Visit(InvokeStaticInstructionNode * instruction)140   void Visit(InvokeStaticInstructionNode* instruction) { }
Visit(AddIntInstructionNode * instruction)141   void Visit(AddIntInstructionNode* instruction) { }
Visit(GotoInstructionNode * instruction)142   void Visit(GotoInstructionNode* instruction) { }
Visit(IfEqzInstructionNode * instruction)143   void Visit(IfEqzInstructionNode* instruction) { }
144   void Visit(PhiInstructionNode* region);
145 };
146 
147 class CodeGenVisitor: public CodeGenPassVisitor {
148  public:
CodeGenVisitor(CodeGenData * code_gen_data,const art::DexFile & dex_file)149   explicit CodeGenVisitor(CodeGenData* code_gen_data,
150       const art::DexFile& dex_file): CodeGenPassVisitor(code_gen_data), dex_file_(dex_file) { }
151   void Visit(SeaGraph* graph);
152   void Visit(SignatureNode* region);
153   void Visit(Region* region);
154   void Visit(InstructionNode* region);
155   void Visit(UnnamedConstInstructionNode* instruction);
156   void Visit(ConstInstructionNode* instruction);
157   void Visit(ReturnInstructionNode* instruction);
158   void Visit(IfNeInstructionNode* instruction);
159   void Visit(MoveResultInstructionNode* instruction);
160   void Visit(InvokeStaticInstructionNode* instruction);
161   void Visit(AddIntInstructionNode* instruction);
162   void Visit(GotoInstructionNode* instruction);
163   void Visit(IfEqzInstructionNode* instruction);
Visit(PhiInstructionNode * region)164   void Visit(PhiInstructionNode* region) { }
165 
166  private:
167   std::string function_name_;
168   const art::DexFile& dex_file_;
169 };
170 }  // namespace sea_ir
171 #endif  // ART_COMPILER_SEA_IR_CODE_GEN_CODE_GEN_H_
172