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