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.
GetInstruction()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.
RenameToSSA(int reg_no,InstructionNode * definition)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().
GetSSAProducers()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   }
GetSSAProducersMap()73   std::map<int, InstructionNode* >* GetSSAProducersMap() {
74     return &definition_edges_;
75   }
GetSSAConsumers()76   std::vector<InstructionNode*>* GetSSAConsumers() {
77     return &used_in_;
78   }
AddSSAUse(InstructionNode * use)79   virtual void AddSSAUse(InstructionNode* use) {
80     used_in_.push_back(use);
81   }
Accept(IRVisitor * v)82   void Accept(IRVisitor* v) {
83     v->Visit(this);
84     v->Traverse(this);
85   }
86   // Set the region to which this instruction belongs.
GetRegion()87   Region* GetRegion() {
88     DCHECK(NULL != region_);
89     return region_;
90   }
91   // Get the region to which this instruction belongs.
SetRegion(Region * region)92   void SetRegion(Region* region) {
93     region_ = region;
94   }
95 
96  protected:
InstructionNode(const art::Instruction * in)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:
ConstInstructionNode(const art::Instruction * inst)111   explicit ConstInstructionNode(const art::Instruction* inst):
112       InstructionNode(inst) { }
113 
Accept(IRVisitor * v)114   void Accept(IRVisitor* v) {
115     v->Visit(this);
116     v->Traverse(this);
117   }
118 
GetConstValue()119   virtual int32_t GetConstValue() const {
120     return GetInstruction()->VRegB_11n();
121   }
122 };
123 
124 class UnnamedConstInstructionNode: public ConstInstructionNode {
125  public:
UnnamedConstInstructionNode(const art::Instruction * inst,int32_t value)126   explicit UnnamedConstInstructionNode(const art::Instruction* inst, int32_t value):
127       ConstInstructionNode(inst), value_(value) { }
128 
Accept(IRVisitor * v)129   void Accept(IRVisitor* v) {
130     v->Visit(this);
131     v->Traverse(this);
132   }
133 
GetResultRegister()134   int GetResultRegister() const {
135     return UNNAMED_CONST_REGISTER;
136   }
137 
GetConstValue()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:
ReturnInstructionNode(const art::Instruction * inst)148   explicit ReturnInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
Accept(IRVisitor * v)149   void Accept(IRVisitor* v) {
150     v->Visit(this);
151     v->Traverse(this);
152   }
153 };
154 
155 class IfNeInstructionNode: public InstructionNode {
156  public:
IfNeInstructionNode(const art::Instruction * inst)157   explicit IfNeInstructionNode(const art::Instruction* inst): InstructionNode(inst) {
158     DCHECK(InstructionTools::IsDefinition(inst) == false);
159   }
Accept(IRVisitor * v)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:
MoveResultInstructionNode(const art::Instruction * inst)170   explicit MoveResultInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
GetUses()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   }
Accept(IRVisitor * v)176   void Accept(IRVisitor* v) {
177     v->Visit(this);
178     v->Traverse(this);
179   }
180 };
181 
182 class InvokeStaticInstructionNode: public InstructionNode {
183  public:
InvokeStaticInstructionNode(const art::Instruction * inst)184   explicit InvokeStaticInstructionNode(const art::Instruction* inst): InstructionNode(inst),
185     method_index_(inst->VRegB_35c()) { }
GetResultRegister()186   int GetResultRegister() const {
187     return RETURN_REGISTER;
188   }
189 
GetCalledMethodIndex()190   int GetCalledMethodIndex() const {
191     return method_index_;
192   }
Accept(IRVisitor * v)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:
AddIntInstructionNode(const art::Instruction * inst)204   explicit AddIntInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
Accept(IRVisitor * v)205   void Accept(IRVisitor* v) {
206     v->Visit(this);
207     v->Traverse(this);
208   }
209 };
210 
211 class AddIntLitInstructionNode: public AddIntInstructionNode {
212  public:
AddIntLitInstructionNode(const art::Instruction * inst)213   explicit AddIntLitInstructionNode(const art::Instruction* inst):
214       AddIntInstructionNode(inst) { }
215 
GetUses()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 
Accept(IRVisitor * v)222   void Accept(IRVisitor* v) {
223     v->Visit(this);
224     v->Traverse(this);
225   }
226 };
227 
228 class GotoInstructionNode: public InstructionNode {
229  public:
GotoInstructionNode(const art::Instruction * inst)230   explicit GotoInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
Accept(IRVisitor * v)231   void Accept(IRVisitor* v) {
232     v->Visit(this);
233     v->Traverse(this);
234   }
235 };
236 
237 class IfEqzInstructionNode: public InstructionNode {
238  public:
IfEqzInstructionNode(const art::Instruction * inst)239   explicit IfEqzInstructionNode(const art::Instruction* inst): InstructionNode(inst) {
240     DCHECK(InstructionTools::IsDefinition(inst) == false);
241   }
Accept(IRVisitor * v)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