1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/* 2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2007 The Android Open Source Project 3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License. 6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at 7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and 14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License. 15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.android.dx.rop.code; 18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.type.StdTypeList; 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.type.Type; 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.type.TypeList; 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.ToHuman; 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * A register-based instruction. An instruction is the combination of 26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * an opcode (which specifies operation and source/result types), a 27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * list of actual sources and result registers/values, and additional 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * information. 29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic abstract class Insn implements ToHuman { 31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} opcode */ 32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final Rop opcode; 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} source position */ 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final SourcePosition position; 36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code null-ok;} spec for the result of this instruction, if any */ 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final RegisterSpec result; 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} specs for all the sources of this instruction */ 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final RegisterSpecList sources; 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Constructs an instance. 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param opcode {@code non-null;} the opcode 47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param position {@code non-null;} source position 48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param result {@code null-ok;} spec for the result, if any 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param sources {@code non-null;} specs for all the sources 50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Insn(Rop opcode, SourcePosition position, RegisterSpec result, 52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpecList sources) { 53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (opcode == null) { 54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new NullPointerException("opcode == null"); 55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (position == null) { 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new NullPointerException("position == null"); 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (sources == null) { 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new NullPointerException("sources == null"); 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.opcode = opcode; 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.position = position; 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.result = result; 68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.sources = sources; 69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@inheritDoc} 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Instances of this class compare by identity. That is, 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code x.equals(y)} is only true if {@code x == y}. 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final boolean equals(Object other) { 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return (this == other); 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@inheritDoc} 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * This implementation returns the identity hashcode of this 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance. This is proper, since instances of this class compare 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * by identity (see {@link #equals}). 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final int hashCode() { 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return System.identityHashCode(this); 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String toString() { 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return toStringWithInline(getInlineString()); 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets a human-oriented (and slightly lossy) string for this instance. 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the human string form 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String toHuman() { 106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return toHumanWithInline(getInlineString()); 107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets an "inline" string portion for toHuman(), if available. This 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * is the portion that appears after the Rop opcode 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code null-ok;} if non-null, the inline text for toHuman() 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String getInlineString() { 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return null; 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the opcode. 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the opcode 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final Rop getOpcode() { 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return opcode; 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the source position. 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the source position 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final SourcePosition getPosition() { 134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return position; 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the result spec, if any. A return value of {@code null} 139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * means this instruction returns nothing. 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code null-ok;} the result spec, if any 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final RegisterSpec getResult() { 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return result; 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the spec of a local variable assignment that occurs at this 149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instruction, or null if no local variable assignment occurs. This 150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * may be the result register, or for {@code mark-local} insns 151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * it may be the source. 152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code null-ok;} a named register spec or null 154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final RegisterSpec getLocalAssignment() { 156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec assignment; 157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (opcode.getOpcode() == RegOps.MARK_LOCAL) { 158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assignment = sources.get(0); 159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson assignment = result; 161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (assignment == null) { 164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return null; 165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson LocalItem localItem = assignment.getLocalItem(); 168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (localItem == null) { 170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return null; 171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return assignment; 174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the source specs. 178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the source specs 180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final RegisterSpecList getSources() { 182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return sources; 183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets whether this instruction can possibly throw an exception. This 187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * is just a convenient wrapper for {@code getOpcode().canThrow()}. 188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code true} iff this instruction can possibly throw 190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final boolean canThrow() { 192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return opcode.canThrow(); 193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the list of possibly-caught exceptions. This returns {@link 197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * StdTypeList#EMPTY} if this instruction has no handlers, 198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * which can be <i>either</i> if this instruction can't possibly 199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * throw or if it merely doesn't handle any of its possible 200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * exceptions. To determine whether this instruction can throw, 201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * use {@link #canThrow}. 202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the catches list 204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public abstract TypeList getCatches(); 206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Calls the appropriate method on the given visitor, depending on the 209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * class of this instance. Subclasses must override this. 210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param visitor {@code non-null;} the visitor to call on 212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 213579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public abstract void accept(Visitor visitor); 214579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 215579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 216579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns an instance that is just like this one, except that it 217579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * has a catch list with the given item appended to the end. This 218579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * method throws an exception if this instance can't possibly 219579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * throw. To determine whether this instruction can throw, use 220579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@link #canThrow}. 221579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 222579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param type {@code non-null;} type to append to the catch list 223579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} an appropriately-constructed instance 224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public abstract Insn withAddedCatch(Type type); 226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns an instance that is just like this one, except that all 229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * register references have been offset by the given delta. 230579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param delta the amount to offset register references by 232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} an appropriately-constructed instance 233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public abstract Insn withRegisterOffset(int delta); 235579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns an instance that is just like this one, except that, if 238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * possible, the insn is converted into a version in which a source 239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * (if it is a constant) is represented directly rather than as a 240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * register reference. {@code this} is returned in cases where the 241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * translation is not possible. 242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} an appropriately-constructed instance 244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Insn withSourceLiteral() { 246579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return this; 247579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 248579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 249579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 250579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns an exact copy of this Insn 251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} an appropriately-constructed instance 253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Insn copy() { 255579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return withRegisterOffset(0); 256579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 257579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 258579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 259579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 260579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Compares, handling nulls safely 261579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param a first object 263579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param b second object 264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return true if they're equal or both null. 265579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static boolean equalsHandleNulls (Object a, Object b) { 267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return (a == b) || ((a != null) && a.equals(b)); 268579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Compares Insn contents, since {@code Insn.equals()} is defined 272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * to be an identity compare. Insn's are {@code contentEquals()} 273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * if they have the same opcode, registers, source position, and other 274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * metadata. 275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return true in the case described above 277579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean contentEquals(Insn b) { 279579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return opcode == b.getOpcode() 280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson && position.equals(b.getPosition()) 281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson && (getClass() == b.getClass()) 282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson && equalsHandleNulls(result, b.getResult()) 283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson && equalsHandleNulls(sources, b.getSources()) 284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson && StdTypeList.equalContents(getCatches(), b.getCatches()); 285579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 287579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 288579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns an instance that is just like this one, except 289579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * with new result and source registers. 290579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 291579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param result {@code null-ok;} new result register 292579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param sources {@code non-null;} new sources registers 293579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} an appropriately-constructed instance 294579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 295579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public abstract Insn withNewRegisters(RegisterSpec result, 296579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpecList sources); 297579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 298579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 299579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns the string form of this instance, with the given bit added in 300579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the standard location for an inline argument. 301579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 302579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param extra {@code null-ok;} the inline argument string 303579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the string form 304579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 305579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson protected final String toStringWithInline(String extra) { 306579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson StringBuffer sb = new StringBuffer(80); 307579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 308579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append("Insn{"); 309579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(position); 310579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(' '); 311579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(opcode); 312579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 313579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (extra != null) { 314579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(' '); 315579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(extra); 316579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 317579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 318579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(" :: "); 319579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 320579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (result != null) { 321579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(result); 322579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(" <- "); 323579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 324579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 325579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(sources); 326579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append('}'); 327579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 328579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return sb.toString(); 329579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 330579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 331579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 332579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns the human string form of this instance, with the given 333579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * bit added in the standard location for an inline argument. 334579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 335579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param extra {@code null-ok;} the inline argument string 336579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the human string form 337579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 338579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson protected final String toHumanWithInline(String extra) { 339579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson StringBuffer sb = new StringBuffer(80); 340579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 341579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(position); 342579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(": "); 343579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(opcode.getNickname()); 344579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 345579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (extra != null) { 346579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append("("); 347579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(extra); 348579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(")"); 349579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 350579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 351579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (result == null) { 352579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(" ."); 353579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 354579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(" "); 355579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(result.toHuman()); 356579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 357579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 358579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(" <-"); 359579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 360579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int sz = sources.size(); 361579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (sz == 0) { 362579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(" ."); 363579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 364579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < sz; i++) { 365579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(" "); 366579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(sources.get(i).toHuman()); 367579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 368579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 369579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 370579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return sb.toString(); 371579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 372579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 373579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 374579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 375579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Visitor interface for this (outer) class. 376579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 377579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static interface Visitor { 378579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 379579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Visits a {@link PlainInsn}. 380579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 381579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param insn {@code non-null;} the instruction to visit 382579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 383579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitPlainInsn(PlainInsn insn); 384579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 385579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 386579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Visits a {@link PlainCstInsn}. 387579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 388579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param insn {@code non-null;} the instruction to visit 389579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 390579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitPlainCstInsn(PlainCstInsn insn); 391579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 392579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 393579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Visits a {@link SwitchInsn}. 394579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 395579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param insn {@code non-null;} the instruction to visit 396579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 397579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitSwitchInsn(SwitchInsn insn); 398579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 399579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 400579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Visits a {@link ThrowingCstInsn}. 401579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 402579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param insn {@code non-null;} the instruction to visit 403579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 404579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitThrowingCstInsn(ThrowingCstInsn insn); 405579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 406579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 407579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Visits a {@link ThrowingInsn}. 408579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 409579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param insn {@code non-null;} the instruction to visit 410579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 411579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitThrowingInsn(ThrowingInsn insn); 412579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 413579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 414579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Visits a {@link FillArrayDataInsn}. 415579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 416579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param insn {@code non-null;} the instruction to visit 417579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 418579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitFillArrayDataInsn(FillArrayDataInsn insn); 419579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 420579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 421579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 422579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Base implementation of {@link Visitor}, which has empty method 423579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * bodies for all methods. 424579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 425579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static class BaseVisitor implements Visitor { 426579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 427579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitPlainInsn(PlainInsn insn) { 428579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // This space intentionally left blank. 429579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 430579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 431579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 432579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitPlainCstInsn(PlainCstInsn insn) { 433579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // This space intentionally left blank. 434579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 435579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 436579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 437579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitSwitchInsn(SwitchInsn insn) { 438579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // This space intentionally left blank. 439579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 440579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 441579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 442579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitThrowingCstInsn(ThrowingCstInsn insn) { 443579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // This space intentionally left blank. 444579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 445579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 446579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 447579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitThrowingInsn(ThrowingInsn insn) { 448579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // This space intentionally left blank. 449579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 450579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 451579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 452579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitFillArrayDataInsn(FillArrayDataInsn insn) { 453579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // This space intentionally left blank. 454579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 455579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 456579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 457