Home | History | Annotate | Download | only in code_gen
      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:
     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.
     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.
     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.
     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.
     49   void AddBlock(Region* region, llvm::BasicBlock* block) {
     50     AddBlock(region->Id(), block);
     51   }
     52 
     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.
     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.
     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.
     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:
     86   explicit CodeGenPassVisitor(CodeGenData* cgd): llvm_data_(cgd) { }
     87   CodeGenPassVisitor(): llvm_data_(new CodeGenData()) { }
     88   // Initialize any data structure needed before the start of visiting.
     89   virtual void Initialize(SeaGraph* graph);
     90   CodeGenData* GetData() {
     91     return llvm_data_;
     92   }
     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:
    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);
    109   void Visit(InstructionNode* instruction) { }
    110 
    111   void Visit(UnnamedConstInstructionNode* instruction) { }
    112   void Visit(ConstInstructionNode* instruction) { }
    113   void Visit(ReturnInstructionNode* instruction) { }
    114   void Visit(IfNeInstructionNode* instruction) { }
    115   // void Visit(AddIntLitInstructionNode* instruction) { }
    116   void Visit(MoveResultInstructionNode* instruction) { }
    117   void Visit(InvokeStaticInstructionNode* instruction) { }
    118   void Visit(AddIntInstructionNode* instruction) { }
    119   void Visit(GotoInstructionNode* 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:
    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);
    133   void Visit(InstructionNode* region) { }
    134   void Visit(UnnamedConstInstructionNode* instruction) { }
    135   void Visit(ConstInstructionNode* instruction) { }
    136   void Visit(ReturnInstructionNode* instruction) { }
    137   void Visit(IfNeInstructionNode* instruction) { }
    138   // void Visit(AddIntLitInstructionNode* instruction) { }
    139   void Visit(MoveResultInstructionNode* instruction) { }
    140   void Visit(InvokeStaticInstructionNode* instruction) { }
    141   void Visit(AddIntInstructionNode* instruction) { }
    142   void Visit(GotoInstructionNode* instruction) { }
    143   void Visit(IfEqzInstructionNode* instruction) { }
    144   void Visit(PhiInstructionNode* region);
    145 };
    146 
    147 class CodeGenVisitor: public CodeGenPassVisitor {
    148  public:
    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);
    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