2 * Copyright (C) 2007 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.dx.ssa;
19 import com.android.dx.rop.code.Insn;
20 import com.android.dx.rop.code.LocalItem;
21 import com.android.dx.rop.code.RegisterSpec;
22 import com.android.dx.rop.code.RegisterSpecList;
23 import com.android.dx.rop.code.Rop;
24 import com.android.dx.util.ToHuman;
27 * An instruction in SSA form
29 public abstract class SsaInsn implements ToHuman, Cloneable {
30 /** {@code non-null;} the block that contains this instance */
31 private final SsaBasicBlock block;
33 /** {@code null-ok;} result register */
34 private RegisterSpec result;
37 * Constructs an instance.
39 * @param result {@code null-ok;} initial result register. May be changed.
40 * @param block {@code non-null;} block containing this insn. Can
43 protected SsaInsn(RegisterSpec result, SsaBasicBlock block) {
45 throw new NullPointerException("block == null");
53 * Makes a new SSA insn form a rop insn.
55 * @param insn {@code non-null;} rop insn
56 * @param block {@code non-null;} owning block
57 * @return {@code non-null;} an appropriately constructed instance
59 public static SsaInsn makeFromRop(Insn insn, SsaBasicBlock block) {
60 return new NormalSsaInsn(insn, block);
65 public SsaInsn clone() {
67 return (SsaInsn)super.clone();
68 } catch (CloneNotSupportedException ex) {
69 throw new RuntimeException ("unexpected", ex);
74 * Like {@link com.android.dx.rop.code.Insn getResult()}.
76 * @return result register
78 public RegisterSpec getResult() {
83 * Set the result register.
85 * @param result {@code non-null;} the new result register
87 protected void setResult(RegisterSpec result) {
89 throw new NullPointerException("result == null");
96 * Like {@link com.android.dx.rop.code.Insn getSources()}.
98 * @return {@code non-null;} sources list
100 abstract public RegisterSpecList getSources();
103 * Gets the block to which this insn instance belongs.
105 * @return owning block
107 public SsaBasicBlock getBlock() {
112 * Returns whether or not the specified reg is the result reg.
114 * @param reg register to test
115 * @return true if there is a result and it is stored in the specified
118 public boolean isResultReg(int reg) {
119 return result != null && result.getReg() == reg;
124 * Changes the result register if this insn has a result. This is used
127 * @param reg new result register
129 public void changeResultReg(int reg) {
130 if (result != null) {
131 result = result.withReg(reg);
136 * Sets the local association for the result of this insn. This is
137 * sometimes updated during the SsaRenamer process.
139 * @param local {@code null-ok;} new debug/local variable info
141 public final void setResultLocal(LocalItem local) {
142 LocalItem oldItem = result.getLocalItem();
144 if (local != oldItem && (local == null
145 || !local.equals(result.getLocalItem()))) {
146 result = RegisterSpec.makeLocalOptional(
147 result.getReg(), result.getType(), local);
152 * Map registers after register allocation.
154 * @param mapper {@code non-null;} mapping from old to new registers
156 public final void mapRegisters(RegisterMapper mapper) {
157 RegisterSpec oldResult = result;
159 result = mapper.map(result);
160 block.getParent().updateOneDefinition(this, oldResult);
161 mapSourceRegisters(mapper);
165 * Maps only source registers.
167 * @param mapper new mapping
169 abstract public void mapSourceRegisters(RegisterMapper mapper);
172 * Returns the Rop opcode for this insn, or null if this is a phi insn.
174 * TODO: Move this up into NormalSsaInsn.
176 * @return {@code null-ok;} Rop opcode if there is one.
178 abstract public Rop getOpcode();
181 * Returns the original Rop insn for this insn, or null if this is
184 * TODO: Move this up into NormalSsaInsn.
186 * @return {@code null-ok;} Rop insn if there is one.
188 abstract public Insn getOriginalRopInsn();
191 * Gets the spec of a local variable assignment that occurs at this
192 * instruction, or null if no local variable assignment occurs. This
193 * may be the result register, or for {@code mark-local} insns
194 * it may be the source.
196 * @see com.android.dx.rop.code.Insn#getLocalAssignment()
198 * @return {@code null-ok;} a local-associated register spec or null
200 public RegisterSpec getLocalAssignment() {
201 if (result != null && result.getLocalItem() != null) {
209 * Indicates whether the specified register is amongst the registers
210 * used as sources for this instruction.
212 * @param reg the register in question
213 * @return true if the reg is a source
215 public boolean isRegASource(int reg) {
216 return null != getSources().specForRegister(reg);
220 * Transform back to ROP form.
222 * TODO: Move this up into NormalSsaInsn.
224 * @return {@code non-null;} a ROP representation of this instruction, with
227 public abstract Insn toRopInsn();
230 * @return true if this is a PhiInsn or a normal move insn
232 public abstract boolean isPhiOrMove();
235 * Returns true if this insn is considered to have a side effect beyond
236 * that of assigning to the result reg.
238 * @return true if this insn is considered to have a side effect beyond
239 * that of assigning to the result reg.
241 public abstract boolean hasSideEffect();
244 * @return true if this is a move (but not a move-operand or
245 * move-exception) instruction
247 public boolean isNormalMoveInsn() {
252 * @return true if this is a move-exception instruction.
253 * These instructions must immediately follow a preceeding invoke*
255 public boolean isMoveException() {
260 * @return true if this instruction can throw.
262 abstract public boolean canThrow();
267 * @param v {@code non-null} the visitor
269 public abstract void accept(Visitor v);
272 * Visitor interface for this class.
274 public static interface Visitor {
276 * Any non-phi move instruction
277 * @param insn {@code non-null;} the instruction to visit
279 public void visitMoveInsn(NormalSsaInsn insn);
283 * @param insn {@code non-null;} the instruction to visit
285 public void visitPhiInsn(PhiInsn insn);
288 * Any insn that isn't a move or a phi (which is also a move).
289 * @param insn {@code non-null;} the instruction to visit
291 public void visitNonMoveInsn(NormalSsaInsn insn);