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 #include <llvm/Support/raw_ostream.h>
     18 
     19 #include "base/logging.h"
     20 #include "utils.h"
     21 
     22 #include "sea_ir/ir/sea.h"
     23 #include "sea_ir/code_gen/code_gen.h"
     24 #include "sea_ir/types/type_inference.h"
     25 #include "sea_ir/types/types.h"
     26 
     27 namespace sea_ir {
     28 
     29 void CodeGenPrepassVisitor::Visit(PhiInstructionNode* phi) {
     30   Region* r = phi->GetRegion();
     31   const std::vector<Region*>* predecessors = r->GetPredecessors();
     32   DCHECK(NULL != predecessors);
     33   DCHECK_GT(predecessors->size(), 0u);
     34   llvm::PHINode *llvm_phi  = llvm_data_->builder_.CreatePHI(
     35       llvm::Type::getInt32Ty(*llvm_data_->context_), predecessors->size(), phi->StringId());
     36   llvm_data_->AddValue(phi, llvm_phi);
     37 }
     38 
     39 void CodeGenPassVisitor::Initialize(SeaGraph* graph) {
     40   Region* root_region;
     41   ordered_regions_.clear();
     42   for (std::vector<Region*>::const_iterator cit = graph->GetRegions()->begin();
     43         cit != graph->GetRegions()->end(); cit++ ) {
     44     if ((*cit)->GetIDominator() == (*cit)) {
     45       root_region = *cit;
     46     }
     47   }
     48   ordered_regions_.push_back(root_region);
     49   for (unsigned int id = 0; id < ordered_regions_.size(); id++) {
     50     Region* current_region = ordered_regions_.at(id);
     51     const std::set<Region*>* dominated_regions = current_region->GetIDominatedSet();
     52     for (std::set<Region*>::const_iterator cit = dominated_regions->begin();
     53             cit != dominated_regions->end(); cit++ ) {
     54       ordered_regions_.push_back(*cit);
     55     }
     56   }
     57 }
     58 
     59 void CodeGenPostpassVisitor::Visit(SeaGraph* graph) { }
     60 void CodeGenVisitor::Visit(SeaGraph* graph) { }
     61 void CodeGenPrepassVisitor::Visit(SeaGraph* graph) {
     62   std::vector<SignatureNode*>* parameters = graph->GetParameterNodes();
     63   // TODO: It may be better to extract correct types from dex
     64   //       instead than from type inference.
     65   DCHECK(parameters != NULL);
     66   std::vector<llvm::Type*> parameter_types;
     67   for (std::vector<SignatureNode*>::const_iterator param_iterator = parameters->begin();
     68       param_iterator!= parameters->end(); param_iterator++) {
     69     const Type* param_type = graph->ti_->type_data_.FindTypeOf((*param_iterator)->Id());
     70     DCHECK(param_type->Equals(graph->ti_->type_cache_->Integer()))
     71       << "Code generation for types other than integer not implemented.";
     72     parameter_types.push_back(llvm::Type::getInt32Ty(*llvm_data_->context_));
     73   }
     74 
     75   // TODO: Get correct function return type.
     76   const Type* return_type = graph->ti_->type_data_.FindTypeOf(-1);
     77   DCHECK(return_type->Equals(graph->ti_->type_cache_->Integer()))
     78     << "Code generation for types other than integer not implemented.";
     79   llvm::FunctionType *function_type = llvm::FunctionType::get(
     80       llvm::Type::getInt32Ty(*llvm_data_->context_),
     81       parameter_types, false);
     82 
     83   llvm_data_->function_ = llvm::Function::Create(function_type,
     84       llvm::Function::ExternalLinkage, function_name_, &llvm_data_->module_);
     85   unsigned param_id = 0;
     86   for (llvm::Function::arg_iterator arg_it = llvm_data_->function_->arg_begin();
     87       param_id != llvm_data_->function_->arg_size(); ++arg_it, ++param_id) {
     88     // TODO: The "+1" is because of the Method parameter on position 0.
     89     DCHECK(parameters->size() > param_id) << "Insufficient parameters for function signature";
     90     // Build parameter register name for LLVM IR clarity.
     91     std::string arg_name = art::StringPrintf("r%d", parameters->at(param_id)->GetResultRegister());
     92     arg_it->setName(arg_name);
     93     SignatureNode* parameter = parameters->at(param_id);
     94     llvm_data_->AddValue(parameter, arg_it);
     95   }
     96 
     97   std::vector<Region*>* regions = &ordered_regions_;
     98   DCHECK_GT(regions->size(), 0u);
     99   // Then create all other basic blocks.
    100   for (std::vector<Region*>::const_iterator cit = regions->begin(); cit != regions->end(); cit++) {
    101     llvm::BasicBlock* new_basic_block = llvm::BasicBlock::Create(*llvm_data_->context_,
    102         (*cit)->StringId(), llvm_data_->function_);
    103     llvm_data_->AddBlock((*cit), new_basic_block);
    104   }
    105 }
    106 
    107 void CodeGenPrepassVisitor::Visit(Region* region) {
    108   llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region));
    109 }
    110 void CodeGenPostpassVisitor::Visit(Region* region) {
    111   llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region));
    112 }
    113 void CodeGenVisitor::Visit(Region* region) {
    114   llvm_data_->builder_.SetInsertPoint(llvm_data_->GetBlock(region));
    115 }
    116 
    117 
    118 void CodeGenVisitor::Visit(InstructionNode* instruction) {
    119   std::string instr = instruction->GetInstruction()->DumpString(NULL);
    120   DCHECK(0);  // This whole function is useful only during development.
    121 }
    122 
    123 void CodeGenVisitor::Visit(UnnamedConstInstructionNode* instruction) {
    124   std::string instr = instruction->GetInstruction()->DumpString(NULL);
    125   std::cout << "1.Instruction: " << instr << std::endl;
    126   llvm_data_->AddValue(instruction,
    127       llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, instruction->GetConstValue())));
    128 }
    129 
    130 void CodeGenVisitor::Visit(ConstInstructionNode* instruction) {
    131   std::string instr = instruction->GetInstruction()->DumpString(NULL);
    132   std::cout << "1.Instruction: " << instr << std::endl;
    133   llvm_data_->AddValue(instruction,
    134       llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, instruction->GetConstValue())));
    135 }
    136 void CodeGenVisitor::Visit(ReturnInstructionNode* instruction) {
    137   std::string instr = instruction->GetInstruction()->DumpString(NULL);
    138   std::cout << "2.Instruction: " << instr << std::endl;
    139   DCHECK_GT(instruction->GetSSAProducers().size(), 0u);
    140   llvm::Value* return_value = llvm_data_->GetValue(instruction->GetSSAProducers().at(0));
    141   llvm_data_->builder_.CreateRet(return_value);
    142 }
    143 void CodeGenVisitor::Visit(IfNeInstructionNode* instruction) {
    144   std::string instr = instruction->GetInstruction()->DumpString(NULL);
    145   std::cout << "3.Instruction: " << instr << std::endl;
    146   std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
    147   DCHECK_GT(ssa_uses.size(), 1u);
    148   InstructionNode* use_l = ssa_uses.at(0);
    149   llvm::Value* left = llvm_data_->GetValue(use_l);
    150 
    151   InstructionNode* use_r = ssa_uses.at(1);
    152   llvm::Value* right = llvm_data_->GetValue(use_r);
    153   llvm::Value* ifne = llvm_data_->builder_.CreateICmpNE(left, right, instruction->StringId());
    154   DCHECK(instruction->GetRegion() != NULL);
    155   std::vector<Region*>* successors = instruction->GetRegion()->GetSuccessors();
    156   DCHECK_GT(successors->size(), 0u);
    157   llvm::BasicBlock* then_block = llvm_data_->GetBlock(successors->at(0));
    158   llvm::BasicBlock* else_block = llvm_data_->GetBlock(successors->at(1));
    159 
    160   llvm_data_->builder_.CreateCondBr(ifne, then_block, else_block);
    161 }
    162 
    163 /*
    164 void CodeGenVisitor::Visit(AddIntLitInstructionNode* instruction) {
    165   std::string instr = instruction->GetInstruction()->DumpString(NULL);
    166   std::cout << "4.Instruction: " << instr << std::endl;
    167   std::vector<InstructionNode*> ssa_uses = instruction->GetSSAUses();
    168   InstructionNode* use_l = ssa_uses.at(0);
    169   llvm::Value* left = llvm_data->GetValue(use_l);
    170   llvm::Value* right = llvm::ConstantInt::get(*llvm_data->context_,
    171       llvm::APInt(32, instruction->GetConstValue()));
    172   llvm::Value* result = llvm_data->builder_.CreateAdd(left, right);
    173   llvm_data->AddValue(instruction, result);
    174 }
    175 */
    176 void CodeGenVisitor::Visit(MoveResultInstructionNode* instruction) {
    177   std::string instr = instruction->GetInstruction()->DumpString(NULL);
    178   std::cout << "5.Instruction: " << instr << std::endl;
    179   // TODO: Currently, this "mov" instruction is simulated by "res = return_register + 0".
    180   // This is inefficient, but should be optimized out by the coalescing phase of the reg alloc.
    181   // The TODO is to either ensure that this happens, or to
    182   // remove the move-result instructions completely from the IR
    183   // by merging them with the invoke-* instructions,
    184   // since their purpose of minimizing the number of opcodes in dex is
    185   // not relevant for the IR. (Will need to have different
    186   // instruction subclasses for functions and procedures.)
    187   std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
    188   InstructionNode* use_l = ssa_uses.at(0);
    189   llvm::Value* left = llvm_data_->GetValue(use_l);
    190   llvm::Value* right = llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, 0));
    191   llvm::Value* result = llvm_data_->builder_.CreateAdd(left, right);
    192   llvm_data_->AddValue(instruction, result);
    193 }
    194 void CodeGenVisitor::Visit(InvokeStaticInstructionNode* invoke) {
    195   std::string instr = invoke->GetInstruction()->DumpString(NULL);
    196   std::cout << "6.Instruction: " << instr << std::endl;
    197   // TODO: Build callee LLVM function name.
    198   std::string symbol = "dex_";
    199   symbol += art::MangleForJni(PrettyMethod(invoke->GetCalledMethodIndex(), dex_file_));
    200   std::string function_name = "dex_int_00020Main_fibonacci_00028int_00029";
    201   llvm::Function *callee = llvm_data_->module_.getFunction(function_name);
    202   // TODO: Add proper checking of the matching between formal and actual signature.
    203   DCHECK(NULL != callee);
    204   std::vector<llvm::Value*> parameter_values;
    205   std::vector<InstructionNode*> parameter_sources = invoke->GetSSAProducers();
    206   // TODO: Replace first parameter with Method argument instead of 0.
    207   parameter_values.push_back(llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, 0)));
    208   for (std::vector<InstructionNode*>::const_iterator cit = parameter_sources.begin();
    209       cit != parameter_sources.end(); ++cit) {
    210     llvm::Value* parameter_value = llvm_data_->GetValue((*cit));
    211     DCHECK(NULL != parameter_value);
    212     parameter_values.push_back(parameter_value);
    213   }
    214   llvm::Value* return_value = llvm_data_->builder_.CreateCall(callee,
    215       parameter_values, invoke->StringId());
    216   llvm_data_->AddValue(invoke, return_value);
    217 }
    218 void CodeGenVisitor::Visit(AddIntInstructionNode* instruction) {
    219   std::string instr = instruction->GetInstruction()->DumpString(NULL);
    220   std::cout << "7.Instruction: " << instr << std::endl;
    221   std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
    222   DCHECK_GT(ssa_uses.size(), 1u);
    223   InstructionNode* use_l = ssa_uses.at(0);
    224   InstructionNode* use_r = ssa_uses.at(1);
    225   llvm::Value* left = llvm_data_->GetValue(use_l);
    226   llvm::Value* right = llvm_data_->GetValue(use_r);
    227   llvm::Value* result = llvm_data_->builder_.CreateAdd(left, right);
    228   llvm_data_->AddValue(instruction, result);
    229 }
    230 void CodeGenVisitor::Visit(GotoInstructionNode* instruction) {
    231   std::string instr = instruction->GetInstruction()->DumpString(NULL);
    232   std::cout << "8.Instruction: " << instr << std::endl;
    233   std::vector<sea_ir::Region*>* targets = instruction->GetRegion()->GetSuccessors();
    234   DCHECK_EQ(targets->size(), 1u);
    235   llvm::BasicBlock* target_block = llvm_data_->GetBlock(targets->at(0));
    236   llvm_data_->builder_.CreateBr(target_block);
    237 }
    238 void CodeGenVisitor::Visit(IfEqzInstructionNode* instruction) {
    239   std::string instr = instruction->GetInstruction()->DumpString(NULL);
    240   std::cout << "9. Instruction: " << instr << "; Id: " <<instruction << std::endl;
    241   std::vector<InstructionNode*> ssa_uses = instruction->GetSSAProducers();
    242   DCHECK_GT(ssa_uses.size(), 0u);
    243   InstructionNode* use_l = ssa_uses.at(0);
    244   llvm::Value* left = llvm_data_->GetValue(use_l);
    245   llvm::Value* ifeqz = llvm_data_->builder_.CreateICmpEQ(left,
    246       llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt::getNullValue(32)),
    247       instruction->StringId());
    248   DCHECK(instruction->GetRegion() != NULL);
    249   std::vector<Region*>* successors = instruction->GetRegion()->GetSuccessors();
    250   DCHECK_GT(successors->size(), 0u);
    251   llvm::BasicBlock* then_block = llvm_data_->GetBlock(successors->at(0));
    252   llvm::BasicBlock* else_block = llvm_data_->GetBlock(successors->at(1));
    253   llvm_data_->builder_.CreateCondBr(ifeqz, then_block, else_block);
    254 }
    255 
    256 void CodeGenPostpassVisitor::Visit(PhiInstructionNode* phi) {
    257   std::cout << "10. Instruction: Phi(" << phi->GetRegisterNumber() << ")" << std::endl;
    258   Region* r = phi->GetRegion();
    259   const std::vector<Region*>* predecessors = r->GetPredecessors();
    260   DCHECK(NULL != predecessors);
    261   DCHECK_GT(predecessors->size(), 0u);
    262   // Prepass (CodeGenPrepassVisitor) should create the phi function value.
    263   llvm::PHINode* llvm_phi = (llvm::PHINode*) llvm_data_->GetValue(phi);
    264   int predecessor_pos = 0;
    265   for (std::vector<Region*>::const_iterator cit = predecessors->begin();
    266       cit != predecessors->end(); ++cit) {
    267     std::vector<InstructionNode*>* defining_instructions = phi->GetSSAUses(predecessor_pos++);
    268     DCHECK_EQ(defining_instructions->size(), 1u);
    269     InstructionNode* defining_instruction = defining_instructions->at(0);
    270     DCHECK(NULL != defining_instruction);
    271     Region* incoming_region = *cit;
    272     llvm::BasicBlock* incoming_basic_block = llvm_data_->GetBlock(incoming_region);
    273     llvm::Value* incoming_value = llvm_data_->GetValue(defining_instruction);
    274     llvm_phi->addIncoming(incoming_value, incoming_basic_block);
    275   }
    276 }
    277 
    278 void CodeGenVisitor::Visit(SignatureNode* signature) {
    279   DCHECK_EQ(signature->GetDefinitions().size(), 1u) <<
    280       "Signature nodes must correspond to a single parameter register.";
    281 }
    282 void CodeGenPrepassVisitor::Visit(SignatureNode* signature) {
    283   DCHECK_EQ(signature->GetDefinitions().size(), 1u) <<
    284       "Signature nodes must correspond to a single parameter register.";
    285 }
    286 void CodeGenPostpassVisitor::Visit(SignatureNode* signature) {
    287   DCHECK_EQ(signature->GetDefinitions().size(), 1u) <<
    288       "Signature nodes must correspond to a single parameter register.";
    289 }
    290 
    291 }  // namespace sea_ir
    292