blob: 63e89e77631e91bd3aaff4c2937b407a3dfc34ef [file] [log] [blame]
Dragos Sbirlea0e260a32013-06-21 09:20:34 -07001/*
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
Dragos Sbirleabfaf44f2013-08-06 15:41:44 -070017#ifndef ART_COMPILER_SEA_IR_IR_INSTRUCTION_NODES_H_
18#define ART_COMPILER_SEA_IR_IR_INSTRUCTION_NODES_H_
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070019#include "dex_instruction-inl.h"
Dragos Sbirleabfaf44f2013-08-06 15:41:44 -070020#include "sea_ir/ir/sea_node.h"
21#include "sea_ir/ir/visitor.h"
Dragos Sbirlea64479192013-08-01 15:38:43 -070022
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070023
24namespace sea_ir {
25
26enum 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
33class 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.
39class 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.
Dragos Sbirlea64479192013-08-01 15:38:43 -070052 virtual std::vector<int> GetUses() const;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070053 // 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));
Dragos Sbirlea90af14d2013-08-15 17:50:16 -070059 DCHECK(NULL != definition) << "SSA definition for register " << reg_no
60 << " used in instruction " << Id() << " not found.";
Dragos Sbirleae2245322013-07-29 14:16:14 -070061 definition->AddSSAUse(this);
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070062 }
63 // Returns the ordered set of Instructions that define the input operands of this instruction.
64 // Precondition: SeaGraph.ConvertToSSA().
Dragos Sbirlea7b89bc02013-08-05 16:24:57 -070065 virtual std::vector<InstructionNode*> GetSSAProducers() {
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070066 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 }
Dragos Sbirlea64479192013-08-01 15:38:43 -070073 std::map<int, InstructionNode* >* GetSSAProducersMap() {
74 return &definition_edges_;
Dragos Sbirleab40eddf2013-07-31 13:37:31 -070075 }
Dragos Sbirlea64479192013-08-01 15:38:43 -070076 std::vector<InstructionNode*>* GetSSAConsumers() {
77 return &used_in_;
78 }
Dragos Sbirleae2245322013-07-29 14:16:14 -070079 virtual void AddSSAUse(InstructionNode* use) {
80 used_in_.push_back(use);
81 }
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070082 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):
Dragos Sbirleae2245322013-07-29 14:16:14 -070098 SeaNode(), instruction_(in), used_in_(), de_def_(false), region_(NULL) { }
Dragos Sbirlea0e260a32013-06-21 09:20:34 -070099
100 protected:
101 const art::Instruction* const instruction_;
Dragos Sbirlea64479192013-08-01 15:38:43 -0700102 std::map<int, InstructionNode* > definition_edges_; // Maps used registers to their definitions.
Dragos Sbirleae2245322013-07-29 14:16:14 -0700103 // Stores pointers to instructions that use the result of the current instruction.
104 std::vector<InstructionNode*> used_in_;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700105 bool de_def_;
106 Region* region_;
107};
108
109class 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
124class UnnamedConstInstructionNode: public ConstInstructionNode {
125 public:
126 explicit UnnamedConstInstructionNode(const art::Instruction* inst, int32_t value):
127 ConstInstructionNode(inst), value_(value) { }
Dragos Sbirlea64479192013-08-01 15:38:43 -0700128
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700129 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
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700142 private:
143 const int32_t value_;
144};
145
146class 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
155class 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
168class MoveResultInstructionNode: public InstructionNode {
169 public:
170 explicit MoveResultInstructionNode(const art::Instruction* inst): InstructionNode(inst) { }
Dragos Sbirlea64479192013-08-01 15:38:43 -0700171 std::vector<int> GetUses() const {
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700172 std::vector<int> uses; // Using vector<> instead of set<> because order matters.
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700173 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
182class InvokeStaticInstructionNode: public InstructionNode {
183 public:
Dragos Sbirlea90af14d2013-08-15 17:50:16 -0700184 explicit InvokeStaticInstructionNode(const art::Instruction* inst): InstructionNode(inst),
185 method_index_(inst->VRegB_35c()) { }
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700186 int GetResultRegister() const {
187 return RETURN_REGISTER;
188 }
Dragos Sbirlea90af14d2013-08-15 17:50:16 -0700189
190 int GetCalledMethodIndex() const {
191 return method_index_;
192 }
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700193 void Accept(IRVisitor* v) {
194 v->Visit(this);
195 v->Traverse(this);
196 }
Dragos Sbirlea90af14d2013-08-15 17:50:16 -0700197
198 private:
199 const uint32_t method_index_;
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700200};
201
202class 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
211class AddIntLitInstructionNode: public AddIntInstructionNode {
212 public:
213 explicit AddIntLitInstructionNode(const art::Instruction* inst):
214 AddIntInstructionNode(inst) { }
215
Dragos Sbirlea64479192013-08-01 15:38:43 -0700216 std::vector<int> GetUses() const {
Dragos Sbirlea0e260a32013-06-21 09:20:34 -0700217 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
228class 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
237class 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};
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700247} // namespace sea_ir
Dragos Sbirleabfaf44f2013-08-06 15:41:44 -0700248#endif // ART_COMPILER_SEA_IR_IR_INSTRUCTION_NODES_H_