SsaInsn.java revision 2ad60cfc28e14ee8f0bb038720836a4696c478ad
1/* 2 * Copyright (C) 2007 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 17package com.android.dx.ssa; 18 19import com.android.dx.rop.code.*; 20import com.android.dx.util.ToHuman; 21 22/** 23 * An instruction in SSA form 24 */ 25public abstract class SsaInsn implements ToHuman, Cloneable { 26 27 protected RegisterSpec result; 28 protected final SsaBasicBlock block; 29 30 /** 31 * Constructs an instance 32 * @param block block containing this insn. Can never change. 33 */ 34 protected SsaInsn(final SsaBasicBlock block) { 35 this.block = block; 36 } 37 38 /** 39 * Makes a new SSA insn form a ROP insn 40 * 41 * @param insn non-null; rop insn 42 * @param block non-null; owning block 43 * @return non-null; an appropriately constructed instance 44 */ 45 public static SsaInsn makeFromRop(Insn insn, SsaBasicBlock block) { 46 return new NormalSsaInsn(insn, block); 47 } 48 49 /** {@inheritDoc} */ 50 @Override 51 public SsaInsn clone() { 52 try { 53 return (SsaInsn)super.clone(); 54 } catch (CloneNotSupportedException ex) { 55 throw new RuntimeException ("unexpected", ex); 56 } 57 } 58 59 /** 60 * Like {@link com.android.dx.rop.code.Insn getResult()}. 61 * @return result register 62 */ 63 public RegisterSpec getResult() { 64 return result; 65 } 66 67 /** 68 * Like {@link com.android.dx.rop.code.Insn getSources()}. 69 * @return non-null; sources list 70 */ 71 abstract public RegisterSpecList getSources(); 72 73 /** 74 * Gets the block to which this insn instance belongs. 75 * 76 * @return owning block 77 */ 78 public SsaBasicBlock getBlock() { 79 return block; 80 } 81 82 /** 83 * is the specified reg the result reg? 84 * @param reg register to test 85 * @return true if there is a result and it is stored in the specified 86 * register 87 */ 88 public boolean isResultReg(int reg) { 89 return result != null && result.getReg() == reg; 90 } 91 92 93 /** 94 * Changes the result register if this insn has a result. 95 * Used during renaming. 96 * @param reg new result register. 97 */ 98 public void changeResultReg(int reg) { 99 if (result != null) { 100 result = result.withReg(reg); 101 } 102 } 103 104 /** 105 * Sets the local association for the result of this insn. 106 * This is sometimes updated during the SsaRenamer process. 107 * 108 * @param local null-ok; New debug/local variable info. 109 */ 110 public final void setResultLocal(LocalItem local) { 111 LocalItem oldItem = result.getLocalItem(); 112 113 if (local != oldItem && (local == null 114 || !local.equals(result.getLocalItem()))) { 115 result = RegisterSpec.makeLocalOptional( 116 result.getReg(), result.getType(), local); 117 } 118 } 119 120 /** 121 * Map registers after register allocation. 122 * 123 * @param mapper 124 */ 125 public final void mapRegisters(RegisterMapper mapper) { 126 RegisterSpec oldResult = result; 127 result = mapper.map(result); 128 block.getParent().updateOneDefinition(this, oldResult); 129 mapSourceRegisters(mapper); 130 } 131 132 /** 133 * Maps only source registers. 134 * 135 * @param mapper new mapping 136 */ 137 abstract public void mapSourceRegisters(RegisterMapper mapper); 138 139 140 /** 141 * Returns the Rop opcode for this insn, or null if this is a phi insn 142 * 143 * TODO move this up into NormalSsaInsn 144 * 145 * @return null-ok; Rop opcode if there is one. 146 */ 147 abstract public Rop getOpcode(); 148 149 /** 150 * Returns the original Rop insn for this insn, or null if this is 151 * a phi insn. 152 * 153 * TODO move this up into NormalSsaInsn 154 * 155 * @return null-ok; Rop insn if there is one. 156 */ 157 abstract public Insn getOriginalRopInsn(); 158 159 /** 160 * Gets the spec of a local variable assignment that occurs at this 161 * instruction, or null if no local variable assignment occurs. This 162 * may be the result register, or for <code>mark-local</code> insns 163 * it may be the source. 164 * 165 * @return null-ok; a local-associated register spec or null 166 * @see com.android.dx.rop.code.Insn#getLocalAssignment() 167 */ 168 public RegisterSpec getLocalAssignment() { 169 if (result != null && result.getLocalItem() != null) { 170 return result; 171 } 172 173 return null; 174 } 175 176 /** 177 * Indicates whether the specified register is amongst the registers 178 * used as sources for this instruction. 179 * @param reg The register in question 180 * @return true if the reg is a source 181 */ 182 public boolean isRegASource(int reg) { 183 return null != getSources().specForRegister(reg); 184 } 185 186 /** 187 * Transform back to ROP form. 188 * 189 * TODO move this up into NormalSsaInsn 190 * 191 * @return non-null; a ROP representation of this instruction, with 192 * updated registers. 193 */ 194 public abstract Insn toRopInsn(); 195 196 /** 197 * @return true if this is a PhiInsn or a normal move insn 198 */ 199 public abstract boolean isPhiOrMove(); 200 201 /** 202 * Returns true if this insn is considered to have a side effect beyond 203 * that of assigning to the result reg. 204 * 205 * @return true if this insn is considered to have a side effect beyond 206 * that of assigning to the result reg. 207 */ 208 public abstract boolean hasSideEffect(); 209 210 /** 211 * @return true if this is a move (but not a move-operand or move-exception) 212 * instruction 213 */ 214 public boolean isNormalMoveInsn() { 215 return false; 216 } 217 218 /** 219 * @return true if this is a move-exception instruction. 220 * These instructions must immediately follow a preceeding invoke* 221 */ 222 public boolean isMoveException() { 223 return false; 224 } 225 226 /** 227 * @return true if this instruction can throw. 228 */ 229 abstract public boolean canThrow(); 230 231 /** 232 * accepts a visitor 233 * @param v visitor 234 */ 235 public abstract void accept(Visitor v); 236 237 /** 238 * Visitor interface for this class. 239 */ 240 public static interface Visitor { 241 242 /** 243 * Any non-phi move instruction 244 * @param insn non-null; the instruction to visit 245 */ 246 public void visitMoveInsn(NormalSsaInsn insn); 247 248 /** 249 * Any phi insn 250 * @param insn non-null; the instruction to visit 251 */ 252 public void visitPhiInsn(PhiInsn insn); 253 254 /** 255 * Any insn that isn't a move or a phi (which is also a move). 256 * @param insn non-null; the instruction to visit 257 */ 258 public void visitNonMoveInsn(NormalSsaInsn insn); 259 } 260} 261