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.*;
20 import com.android.dx.util.ToHuman;
23 * An instruction in SSA form
25 public abstract class SsaInsn implements ToHuman, Cloneable {
26 /** {@code non-null;} the block that contains this instance */
27 private final SsaBasicBlock block;
29 /** {@code null-ok;} result register */
30 private RegisterSpec result;
33 * Constructs an instance.
35 * @param result {@code null-ok;} initial result register. May be changed.
36 * @param block {@code non-null;} block containing this insn. Can
39 protected SsaInsn(RegisterSpec result, SsaBasicBlock block) {
41 throw new NullPointerException("block == null");
49 * Makes a new SSA insn form a rop insn.
51 * @param insn {@code non-null;} rop insn
52 * @param block {@code non-null;} owning block
53 * @return {@code non-null;} an appropriately constructed instance
55 public static SsaInsn makeFromRop(Insn insn, SsaBasicBlock block) {
56 return new NormalSsaInsn(insn, block);
61 public SsaInsn clone() {
63 return (SsaInsn)super.clone();
64 } catch (CloneNotSupportedException ex) {
65 throw new RuntimeException ("unexpected", ex);
70 * Like {@link com.android.dx.rop.code.Insn getResult()}.
72 * @return result register
74 public RegisterSpec getResult() {
79 * Set the result register.
81 * @param result {@code non-null;} the new result register
83 protected void setResult(RegisterSpec result) {
85 throw new NullPointerException("result == null");
92 * Like {@link com.android.dx.rop.code.Insn getSources()}.
94 * @return {@code non-null;} sources list
96 abstract public RegisterSpecList getSources();
99 * Gets the block to which this insn instance belongs.
101 * @return owning block
103 public SsaBasicBlock getBlock() {
108 * Returns whether or not the specified reg is the result reg.
110 * @param reg register to test
111 * @return true if there is a result and it is stored in the specified
114 public boolean isResultReg(int reg) {
115 return result != null && result.getReg() == reg;
120 * Changes the result register if this insn has a result. This is used
123 * @param reg new result register
125 public void changeResultReg(int reg) {
126 if (result != null) {
127 result = result.withReg(reg);
132 * Sets the local association for the result of this insn. This is
133 * sometimes updated during the SsaRenamer process.
135 * @param local {@code null-ok;} new debug/local variable info
137 public final void setResultLocal(LocalItem local) {
138 LocalItem oldItem = result.getLocalItem();
140 if (local != oldItem && (local == null
141 || !local.equals(result.getLocalItem()))) {
142 result = RegisterSpec.makeLocalOptional(
143 result.getReg(), result.getType(), local);
148 * Map registers after register allocation.
150 * @param mapper {@code non-null;} mapping from old to new registers
152 public final void mapRegisters(RegisterMapper mapper) {
153 RegisterSpec oldResult = result;
155 result = mapper.map(result);
156 block.getParent().updateOneDefinition(this, oldResult);
157 mapSourceRegisters(mapper);
161 * Maps only source registers.
163 * @param mapper new mapping
165 abstract public void mapSourceRegisters(RegisterMapper mapper);
168 * Returns the Rop opcode for this insn, or null if this is a phi insn.
170 * TODO: Move this up into NormalSsaInsn.
172 * @return {@code null-ok;} Rop opcode if there is one.
174 abstract public Rop getOpcode();
177 * Returns the original Rop insn for this insn, or null if this is
180 * TODO: Move this up into NormalSsaInsn.
182 * @return {@code null-ok;} Rop insn if there is one.
184 abstract public Insn getOriginalRopInsn();
187 * Gets the spec of a local variable assignment that occurs at this
188 * instruction, or null if no local variable assignment occurs. This
189 * may be the result register, or for {@code mark-local} insns
190 * it may be the source.
192 * @see com.android.dx.rop.code.Insn#getLocalAssignment()
194 * @return {@code null-ok;} a local-associated register spec or null
196 public RegisterSpec getLocalAssignment() {
197 if (result != null && result.getLocalItem() != null) {
205 * Indicates whether the specified register is amongst the registers
206 * used as sources for this instruction.
208 * @param reg the register in question
209 * @return true if the reg is a source
211 public boolean isRegASource(int reg) {
212 return null != getSources().specForRegister(reg);
216 * Transform back to ROP form.
218 * TODO: Move this up into NormalSsaInsn.
220 * @return {@code non-null;} a ROP representation of this instruction, with
223 public abstract Insn toRopInsn();
226 * @return true if this is a PhiInsn or a normal move insn
228 public abstract boolean isPhiOrMove();
231 * Returns true if this insn is considered to have a side effect beyond
232 * that of assigning to the result reg.
234 * @return true if this insn is considered to have a side effect beyond
235 * that of assigning to the result reg.
237 public abstract boolean hasSideEffect();
240 * @return true if this is a move (but not a move-operand or
241 * move-exception) instruction
243 public boolean isNormalMoveInsn() {
248 * @return true if this is a move-exception instruction.
249 * These instructions must immediately follow a preceeding invoke*
251 public boolean isMoveException() {
256 * @return true if this instruction can throw.
258 abstract public boolean canThrow();
263 * @param v {@code non-null} the visitor
265 public abstract void accept(Visitor v);
268 * Visitor interface for this class.
270 public static interface Visitor {
272 * Any non-phi move instruction
273 * @param insn {@code non-null;} the instruction to visit
275 public void visitMoveInsn(NormalSsaInsn insn);
279 * @param insn {@code non-null;} the instruction to visit
281 public void visitPhiInsn(PhiInsn insn);
284 * Any insn that isn't a move or a phi (which is also a move).
285 * @param insn {@code non-null;} the instruction to visit
287 public void visitNonMoveInsn(NormalSsaInsn insn);