Home | History | Annotate | Download | only in ir
      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_IR_INSTRUCTION_NODES_H_
     18 #define ART_COMPILER_SEA_IR_IR_INSTRUCTION_NODES_H_
     19 #include "dex_instruction-inl.h"
     20 #include "sea_ir/ir/sea_node.h"
     21 #include "sea_ir/ir/visitor.h"
     22 
     23 
     24 namespace sea_ir {
     25 
     26 enum SpecialRegisters {
     27   NO_REGISTER = -1,             // Usually signifies that there is no register
     28                                 // that respects the condition you asked for.
     29   RETURN_REGISTER = -2,         // Written by the invoke* instructions, read by move-results.
     30   UNNAMED_CONST_REGISTER = -3   // Written by UnnamedConst* instructions, read by *Lit* instruction.
     31 };
     32 
     33 class IRVisitor;
     34 
     35 // This class represents an instruction in SEA IR.
     36 // As we add support for specific classes of instructions,
     37 // the number of InstructionNode objects should dwindle, while the
     38 // number of subclasses and instances of subclasses will go up.
     39 class InstructionNode: public SeaNode {
     40  public:
     41   static std::vector<sea_ir::InstructionNode*> Create(const art::Instruction* in);
     42   // Returns the Dalvik instruction around which this InstructionNode is wrapped.
     43   const art::Instruction* GetInstruction() const {
     44     DCHECK(NULL != instruction_) << "Tried to access NULL instruction in an InstructionNode.";
     45     return instruction_;
     46   }
     47   // Returns the register that is defined by the current instruction, or NO_REGISTER otherwise.
     48   virtual int GetResultRegister() const;
     49   // Returns the set of registers defined by the current instruction.
     50   virtual std::vector<int> GetDefinitions() const;
     51   // Returns the set of register numbers that are used by the instruction.
     52   virtual std::vector<int> GetUses() const;
     53   // Mark the current instruction as a downward exposed definition.
     54   void MarkAsDEDef();
     55   // Rename the use of @reg_no to refer to the instruction @definition,
     56   // essentially creating SSA form.
     57   void RenameToSSA(int reg_no, InstructionNode* definition) {
     58     definition_edges_.insert(std::pair<int, InstructionNode*>(reg_no, definition));
     59     DCHECK(NULL != definition) << "SSA definition for register " << reg_no
     60         << " used in instruction " << Id() << " not found.";
     61     definition->AddSSAUse(this);
     62   }
     63   // Returns the ordered set of Instructions that define the input operands of this instruction.
     64   // Precondition: SeaGraph.ConvertToSSA().
     65   virtual std::vector<InstructionNode*> GetSSAProducers() {
     66     std::vector<int> uses = GetUses();
     67     std::vector<InstructionNode*> ssa_uses;
     68     for (std::vector<int>::const_iterator cit = uses.begin(); cit != uses.end(); cit++) {
     69       ssa_uses.push_back((*definition_edges_.find(*cit)).second);
     70     }
     71     return ssa_uses;
     72   }
     73   std::map<int, InstructionNode* >* GetSSAProducersMap() {
     74     return &definition_edges_;
     75   }
     76   std::vector<InstructionNode*>* GetSSAConsumers() {
     77     return &used_in_;
     78   }
     79   virtual void AddSSAUse(InstructionNode* use) {
     80     used_in_.push_back(use);
     81   }
     82   void Accept(IRVisitor* v) {
     83     v->Visit(this);
     84     v->Traverse(this);
     85   }
     86   // Set the region to which this instruction belongs.
     87   Region* GetRegion() {
     88     DCHECK(NULL != region_);
     89     return region_;
     90   }
     91   // Get the region to which this instruction belongs.
     92   void SetRegion(Region* region) {
     93     region_ = region;
     94   }
     95 
     96  protected:
     97   explicit InstructionNode(const art::Instruction* in):
     98       SeaNode(), instruction_(in), used_in_(), de_def_(false), region_(NULL) { }
     99 
    100  protected:
    101   const art::Instruction* const instruction_;
    102   std::map<int, InstructionNode* > definition_edges_;  // Maps used registers to their definitions.
    103   // Stores pointers to instructions that use the result of the current instruction.
    104   std::vector<InstructionNode*> used_in_;
    105   bool de_def_;
    106   Region* region_;
    107 };
    108 
    109 class ConstInstructionNode: public InstructionNode {
    110  public:
    111   explicit ConstInstructionNode(const art::Instruction* inst):
    112       InstructionNode(inst) { }
    113 
    114   void Accept(IRVisitor* v) {
    115     v->Visit(this);
    116     v->Traverse(this);
    117   }
    118 
    119   virtual int32_t GetConstValue() const {
    120     return GetInstruction()->VRegB_11n();
    121   }
    122 };
    123 
    124 class UnnamedConstInstructionNode: public ConstInstructionNode {
    125  public:
    126   explicit UnnamedConstInstructionNode(const art::Instruction* inst, int32_t value):
    127       ConstInstructionNode(inst), value_(value) { }
    128 
    129   void Accept(IRVisitor* v) {
    130     v->Visit(this);
    131     v->Traverse(this);
    132   }
    133 
    134   int GetResultRegister() const {
    135     return UNNAMED_CONST_REGISTER;
    136   }
    137 
    138   int32_t GetConstValue() const {
    139     return value_;
    140   }
    141 
    142  private:
    143   const int32_t value_;
    144 };
    145 
    146 class ReturnInstructionNode: public InstructionNode {
    147  public:
    148   explicit ReturnInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
    149   void Accept(IRVisitor* v) {
    150     v->Visit(this);
    151     v->Traverse(this);
    152   }
    153 };
    154 
    155 class IfNeInstructionNode: public InstructionNode {
    156  public:
    157   explicit IfNeInstructionNode(const art::Instruction* inst): InstructionNode(inst) {
    158     DCHECK(InstructionTools::IsDefinition(inst) == false);
    159   }
    160   void Accept(IRVisitor* v) {
    161     v->Visit(this);
    162     v->Traverse(this);
    163   }
    164 };
    165 
    166 
    167 
    168 class MoveResultInstructionNode: public InstructionNode {
    169  public:
    170   explicit MoveResultInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
    171   std::vector<int> GetUses() const {
    172     std::vector<int> uses;  // Using vector<> instead of set<> because order matters.
    173     uses.push_back(RETURN_REGISTER);
    174     return uses;
    175   }
    176   void Accept(IRVisitor* v) {
    177     v->Visit(this);
    178     v->Traverse(this);
    179   }
    180 };
    181 
    182 class InvokeStaticInstructionNode: public InstructionNode {
    183  public:
    184   explicit InvokeStaticInstructionNode(const art::Instruction* inst): InstructionNode(inst),
    185     method_index_(inst->VRegB_35c()) { }
    186   int GetResultRegister() const {
    187     return RETURN_REGISTER;
    188   }
    189 
    190   int GetCalledMethodIndex() const {
    191     return method_index_;
    192   }
    193   void Accept(IRVisitor* v) {
    194     v->Visit(this);
    195     v->Traverse(this);
    196   }
    197 
    198  private:
    199   const uint32_t method_index_;
    200 };
    201 
    202 class AddIntInstructionNode: public InstructionNode {
    203  public:
    204   explicit AddIntInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
    205   void Accept(IRVisitor* v) {
    206     v->Visit(this);
    207     v->Traverse(this);
    208   }
    209 };
    210 
    211 class AddIntLitInstructionNode: public AddIntInstructionNode {
    212  public:
    213   explicit AddIntLitInstructionNode(const art::Instruction* inst):
    214       AddIntInstructionNode(inst) { }
    215 
    216   std::vector<int> GetUses() const {
    217     std::vector<int> uses =  AddIntInstructionNode::GetUses();
    218     uses.push_back(UNNAMED_CONST_REGISTER);
    219     return uses;
    220     }
    221 
    222   void Accept(IRVisitor* v) {
    223     v->Visit(this);
    224     v->Traverse(this);
    225   }
    226 };
    227 
    228 class GotoInstructionNode: public InstructionNode {
    229  public:
    230   explicit GotoInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
    231   void Accept(IRVisitor* v) {
    232     v->Visit(this);
    233     v->Traverse(this);
    234   }
    235 };
    236 
    237 class IfEqzInstructionNode: public InstructionNode {
    238  public:
    239   explicit IfEqzInstructionNode(const art::Instruction* inst): InstructionNode(inst) {
    240     DCHECK(InstructionTools::IsDefinition(inst) == false);
    241   }
    242   void Accept(IRVisitor* v) {
    243     v->Visit(this);
    244     v->Traverse(this);
    245   }
    246 };
    247 }  // namespace sea_ir
    248 #endif  // ART_COMPILER_SEA_IR_IR_INSTRUCTION_NODES_H_
    249