1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/* 2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project 3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License"); 5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License. 6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at 7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * http://www.apache.org/licenses/LICENSE-2.0 9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software 11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS, 12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and 14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License. 15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.rop.code; 18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.Constant; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstUtf8; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.StdTypeList; 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.Type; 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.TypeList; 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.ToHuman; 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * A register-based instruction. An instruction is the combination of 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * an opcode (which specifies operation and source/result types), a 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * list of actual sources and result registers/values, and additional 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * information. 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic abstract class Insn implements ToHuman { 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} opcode */ 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final Rop opcode; 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} source position */ 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final SourcePosition position; 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code null-ok;} spec for the result of this instruction, if any */ 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final RegisterSpec result; 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} specs for all the sources of this instruction */ 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final RegisterSpecList sources; 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param opcode {@code non-null;} the opcode 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param position {@code non-null;} source position 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param result {@code null-ok;} spec for the result, if any 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param sources {@code non-null;} specs for all the sources 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public Insn(Rop opcode, SourcePosition position, RegisterSpec result, 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecList sources) { 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (opcode == null) { 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("opcode == null"); 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (position == null) { 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("position == null"); 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (sources == null) { 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("sources == null"); 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.opcode = opcode; 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.position = position; 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.result = result; 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.sources = sources; 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@inheritDoc} 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Instances of this class compare by identity. That is, 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code x.equals(y)} is only true if {@code x == y}. 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final boolean equals(Object other) { 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (this == other); 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@inheritDoc} 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * This implementation returns the identity hashcode of this 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance. This is proper, since instances of this class compare 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * by identity (see {@link #equals}). 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final int hashCode() { 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return System.identityHashCode(this); 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public String toString() { 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return toStringWithInline(getInlineString()); 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets a human-oriented (and slightly lossy) string for this instance. 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the human string form 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public String toHuman() { 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return toHumanWithInline(getInlineString()); 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets an "inline" string portion for toHuman(), if available. This 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * is the portion that appears after the Rop opcode 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} if non-null, the inline text for toHuman() 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public String getInlineString() { 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the opcode. 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the opcode 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final Rop getOpcode() { 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return opcode; 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the source position. 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the source position 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final SourcePosition getPosition() { 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return position; 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the result spec, if any. A return value of {@code null} 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * means this instruction returns nothing. 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} the result spec, if any 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final RegisterSpec getResult() { 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the spec of a local variable assignment that occurs at this 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instruction, or null if no local variable assignment occurs. This 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * may be the result register, or for {@code mark-local} insns 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * it may be the source. 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} a named register spec or null 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final RegisterSpec getLocalAssignment() { 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec assignment; 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (opcode.getOpcode() == RegOps.MARK_LOCAL) { 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul assignment = sources.get(0); 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul assignment = result; 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (assignment == null) { 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul LocalItem localItem = assignment.getLocalItem(); 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (localItem == null) { 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return assignment; 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the source specs. 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the source specs 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final RegisterSpecList getSources() { 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sources; 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets whether this instruction can possibly throw an exception. This 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * is just a convenient wrapper for {@code getOpcode().canThrow()}. 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff this instruction can possibly throw 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final boolean canThrow() { 194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return opcode.canThrow(); 195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the list of possibly-caught exceptions. This returns {@link 199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * StdTypeList#EMPTY} if this instruction has no handlers, 200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * which can be <i>either</i> if this instruction can't possibly 201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * throw or if it merely doesn't handle any of its possible 202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * exceptions. To determine whether this instruction can throw, 203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * use {@link #canThrow}. 204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the catches list 206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public abstract TypeList getCatches(); 208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Calls the appropriate method on the given visitor, depending on the 211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * class of this instance. Subclasses must override this. 212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param visitor {@code non-null;} the visitor to call on 214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public abstract void accept(Visitor visitor); 216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an instance that is just like this one, except that it 219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * has a catch list with the given item appended to the end. This 220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * method throws an exception if this instance can't possibly 221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * throw. To determine whether this instruction can throw, use 222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@link #canThrow}. 223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param type {@code non-null;} type to append to the catch list 225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public abstract Insn withAddedCatch(Type type); 228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an instance that is just like this one, except that all 231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * register references have been offset by the given delta. 232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param delta the amount to offset register references by 234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public abstract Insn withRegisterOffset(int delta); 237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an instance that is just like this one, except that, if 240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * possible, the insn is converted into a version in which the last 241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * source (if it is a constant) is represented directly rather than 242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * as a register reference. {@code this} is returned in cases where 243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the translation is not possible. 244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public Insn withLastSourceLiteral() { 248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return this; 249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an exact copy of this Insn 253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public Insn copy() { 257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return withRegisterOffset(0); 258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Compares, handling nulls safely 263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param a first object 265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param b second object 266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return true if they're equal or both null. 267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static boolean equalsHandleNulls (Object a, Object b) { 269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (a == b) || ((a != null) && a.equals(b)); 270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Compares Insn contents, since {@code Insn.equals()} is defined 274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * to be an identity compare. Insn's are {@code contentEquals()} 275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * if they have the same opcode, registers, source position, and other 276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * metadata. 277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return true in the case described above 279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean contentEquals(Insn b) { 281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return opcode == b.getOpcode() 282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && position.equals(b.getPosition()) 283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && (getClass() == b.getClass()) 284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && equalsHandleNulls(result, b.getResult()) 285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && equalsHandleNulls(sources, b.getSources()) 286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && StdTypeList.equalContents(getCatches(), b.getCatches()); 287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an instance that is just like this one, except 291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * with new result and source registers. 292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param result {@code null-ok;} new result register 294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param sources {@code non-null;} new sources registers 295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public abstract Insn withNewRegisters(RegisterSpec result, 298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecList sources); 299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns the string form of this instance, with the given bit added in 302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the standard location for an inline argument. 303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param extra {@code null-ok;} the inline argument string 305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the string form 306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected final String toStringWithInline(String extra) { 308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuffer sb = new StringBuffer(80); 309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append("Insn{"); 311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(position); 312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(' '); 313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(opcode); 314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (extra != null) { 316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(' '); 317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(extra); 318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(" :: "); 321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (result != null) { 323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(result); 324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(" <- "); 325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(sources); 328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append('}'); 329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns the human string form of this instance, with the given 335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * bit added in the standard location for an inline argument. 336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param extra {@code null-ok;} the inline argument string 338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the human string form 339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul protected final String toHumanWithInline(String extra) { 341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuffer sb = new StringBuffer(80); 342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(position); 344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(": "); 345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(opcode.getNickname()); 346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (extra != null) { 348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append("("); 349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(extra); 350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(")"); 351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (result == null) { 354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(" ."); 355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(" "); 357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(result.toHuman()); 358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(" <-"); 361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 362917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = sources.size(); 363917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (sz == 0) { 364917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(" ."); 365917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 366917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 367917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(" "); 368917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(sources.get(i).toHuman()); 369917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 370917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 371917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 372917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 373917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 374917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 375917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 376917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 377917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Visitor interface for this (outer) class. 378917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 379917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static interface Visitor { 380917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 381917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Visits a {@link PlainInsn}. 382917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 383917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction to visit 384917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 385917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitPlainInsn(PlainInsn insn); 386917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 387917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 388917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Visits a {@link PlainCstInsn}. 389917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 390917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction to visit 391917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 392917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitPlainCstInsn(PlainCstInsn insn); 393917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 394917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 395917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Visits a {@link SwitchInsn}. 396917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 397917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction to visit 398917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 399917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitSwitchInsn(SwitchInsn insn); 400917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 401917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 402917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Visits a {@link ThrowingCstInsn}. 403917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 404917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction to visit 405917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 406917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitThrowingCstInsn(ThrowingCstInsn insn); 407917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 408917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 409917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Visits a {@link ThrowingInsn}. 410917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 411917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction to visit 412917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 413917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitThrowingInsn(ThrowingInsn insn); 414917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 415917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 416917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Visits a {@link FillArrayDataInsn}. 417917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 418917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param insn {@code non-null;} the instruction to visit 419917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 420917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitFillArrayDataInsn(FillArrayDataInsn insn); 421917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 422917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 423917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 424917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Base implementation of {@link Visitor}, which has empty method 425917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * bodies for all methods. 426917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 427917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static class BaseVisitor implements Visitor { 428917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 429917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitPlainInsn(PlainInsn insn) { 430917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // This space intentionally left blank. 431917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 432917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 433917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 434917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitPlainCstInsn(PlainCstInsn insn) { 435917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // This space intentionally left blank. 436917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 437917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 438917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 439917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitSwitchInsn(SwitchInsn insn) { 440917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // This space intentionally left blank. 441917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 442917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 443917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 444917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitThrowingCstInsn(ThrowingCstInsn insn) { 445917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // This space intentionally left blank. 446917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 447917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 448917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 449917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitThrowingInsn(ThrowingInsn insn) { 450917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // This space intentionally left blank. 451917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 452917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 453917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 454917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void visitFillArrayDataInsn(FillArrayDataInsn insn) { 455917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // This space intentionally left blank. 456917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 457917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 458917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 459