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.cst.Constant; 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.CstString; 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.type.Type; 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.type.TypeBearer; 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.ToHuman; 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.HashMap; 26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Combination of a register number and a type, used as the sources and 29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * destinations of register-based operations. 30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic final class RegisterSpec 32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson implements TypeBearer, ToHuman, Comparable<RegisterSpec> { 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} string to prefix register numbers with */ 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static final String PREFIX = "v"; 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} intern table for instances */ 37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static final HashMap<Object, RegisterSpec> theInterns = 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson new HashMap<Object, RegisterSpec>(1000); 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} common comparison instance used while interning */ 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static final ForComparison theInterningItem = new ForComparison(); 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code >= 0;} register number */ 44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final int reg; 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} type loaded or stored */ 47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final TypeBearer type; 48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code null-ok;} local variable info associated with this register, 51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * if any 52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final LocalItem local; 54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Intern the given triple as an instance of this class. 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param reg {@code >= 0;} the register number 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param type {@code non-null;} the type (or possibly actual value) which 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * is loaded from or stored to the indicated register 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param local {@code null-ok;} the associated local variable, if any 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} an appropriately-constructed instance 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static RegisterSpec intern(int reg, TypeBearer type, 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson LocalItem local) { 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson synchronized (theInterns) { 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson theInterningItem.set(reg, type, local); 68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec found = theInterns.get(theInterningItem); 69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (found != null) { 71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return found; 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson found = theInterningItem.toRegisterSpec(); 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson theInterns.put(found, found); 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return found; 77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns an instance for the given register number and type, with 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * no variable info. This method is allowed to return shared 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instances (but doesn't necessarily do so). 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param reg {@code >= 0;} the register number 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param type {@code non-null;} the type (or possibly actual value) which 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * is loaded from or stored to the indicated register 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} an appropriately-constructed instance 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static RegisterSpec make(int reg, TypeBearer type) { 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return intern(reg, type, null); 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns an instance for the given register number, type, and 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * variable info. This method is allowed to return shared 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instances (but doesn't necessarily do so). 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param reg {@code >= 0;} the register number 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param type {@code non-null;} the type (or possibly actual value) which 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * is loaded from or stored to the indicated register 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param local {@code non-null;} the associated local variable 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} an appropriately-constructed instance 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static RegisterSpec make(int reg, TypeBearer type, 106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson LocalItem local) { 107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (local == null) { 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new NullPointerException("local == null"); 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return intern(reg, type, local); 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns an instance for the given register number, type, and 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * variable info. This method is allowed to return shared 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instances (but doesn't necessarily do so). 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param reg {@code >= 0;} the register number 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param type {@code non-null;} the type (or possibly actual value) which 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * is loaded from or stored to the indicated register 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param local {@code null-ok;} the associated variable info or null for 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * none 124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} an appropriately-constructed instance 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static RegisterSpec makeLocalOptional( 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int reg, TypeBearer type, LocalItem local) { 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return intern(reg, type, local); 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the string form for the given register number. 134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param reg {@code >= 0;} the register number 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the string form 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static String regString(int reg) { 139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return PREFIX + reg; 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Constructs an instance. This constructor is private. Use 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@link #make}. 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param reg {@code >= 0;} the register number 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param type {@code non-null;} the type (or possibly actual value) which 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * is loaded from or stored to the indicated register 149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param local {@code null-ok;} the associated local variable, if any 150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private RegisterSpec(int reg, TypeBearer type, LocalItem local) { 152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (reg < 0) { 153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IllegalArgumentException("reg < 0"); 154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (type == null) { 157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new NullPointerException("type == null"); 158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.reg = reg; 161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.type = type; 162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.local = local; 163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean equals(Object other) { 168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (!(other instanceof RegisterSpec)) { 169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (other instanceof ForComparison) { 170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ForComparison fc = (ForComparison) other; 171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return equals(fc.reg, fc.type, fc.local); 172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; 174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec spec = (RegisterSpec) other; 177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return equals(spec.reg, spec.type, spec.local); 178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Like {@code equals}, but only consider the simple types of the 182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * registers. That is, this compares {@code getType()} on the types 183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * to ignore whatever arbitrary extra stuff might be carried around 184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * by an outer {@link TypeBearer}. 185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param other {@code null-ok;} spec to compare to 187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code true} iff {@code this} and {@code other} are equal 188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * in the stated way 189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean equalsUsingSimpleType(RegisterSpec other) { 191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (!matchesVariable(other)) { 192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; 193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return (reg == other.reg); 196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Like {@link #equalsUsingSimpleType} but ignoring the register number. 200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * This is useful to determine if two instances refer to the "same" 201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * local variable. 202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param other {@code null-ok;} spec to compare to 204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code true} iff {@code this} and {@code other} are equal 205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * in the stated way 206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean matchesVariable(RegisterSpec other) { 208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (other == null) { 209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; 210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return type.getType().equals(other.type.getType()) 213579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson && ((local == other.local) 214579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson || ((local != null) && local.equals(other.local))); 215579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 216579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 217579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 218579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Helper for {@link #equals} and {@link #ForComparison.equals}, 219579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * which actually does the test. 220579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 221579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param reg value of the instance variable, for another instance 222579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param type value of the instance variable, for another instance 223579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param local value of the instance variable, for another instance 224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return whether this instance is equal to one with the given 225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * values 226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private boolean equals(int reg, TypeBearer type, LocalItem local) { 228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return (this.reg == reg) 229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson && this.type.equals(type) 230579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson && ((this.local == local) 231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson || ((this.local != null) && this.local.equals(local))); 232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 235579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Compares by (in priority order) register number, unwrapped type 236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * (that is types not {@link TypeBearer}s, and local info. 237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param other {@code non-null;} spec to compare to 239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code -1..1;} standard result of comparison 240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int compareTo(RegisterSpec other) { 242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (this.reg < other.reg) { 243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return -1; 244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else if (this.reg > other.reg) { 245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return 1; 246579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 247579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 248579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int compare = type.getType().compareTo(other.type.getType()); 249579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 250579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (compare != 0) { 251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return compare; 252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (this.local == null) { 255579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return (other.local == null) ? 0 : -1; 256579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else if (other.local == null) { 257579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return 1; 258579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 259579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 260579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return this.local.compareTo(other.local); 261579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 263579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 265579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int hashCode() { 266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return hashCodeOf(reg, type, local); 267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 268579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Helper for {@link #hashCode} and {@link #ForComparison.hashCode}, 271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * which actually does the calculation. 272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param reg value of the instance variable 274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param type value of the instance variable 275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param local value of the instance variable 276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return the hash code 277579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static int hashCodeOf(int reg, TypeBearer type, LocalItem local) { 279579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int hash = (local != null) ? local.hashCode() : 0; 280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson hash = (hash * 31 + type.hashCode()) * 31 + reg; 282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return hash; 283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 285579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 287579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String toString() { 288579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return toString0(false); 289579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 290579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 291579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 292579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String toHuman() { 293579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return toString0(true); 294579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 295579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 296579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 297579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Type getType() { 298579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return type.getType(); 299579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 300579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 301579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 302579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public TypeBearer getFrameType() { 303579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return type.getFrameType(); 304579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 305579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 306579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 307579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final int getBasicType() { 308579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return type.getBasicType(); 309579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 310579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 311579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 312579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final int getBasicFrameType() { 313579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return type.getBasicFrameType(); 314579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 315579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 316579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 317579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final boolean isConstant() { 318579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; 319579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 320579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 321579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 322579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the register number. 323579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 324579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code >= 0;} the register number 325579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 326579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int getReg() { 327579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return reg; 328579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 329579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 330579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 331579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the type (or actual value) which is loaded from or stored 332579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * to the register associated with this instance. 333579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 334579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the type 335579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 336579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public TypeBearer getTypeBearer() { 337579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return type; 338579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 339579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 340579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 341579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the variable info associated with this instance, if any. 342579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 343579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code null-ok;} the variable info, or {@code null} if this 344579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance has none 345579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 346579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public LocalItem getLocalItem() { 347579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return local; 348579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 349579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 350579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 351579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the next available register number after the one in this 352579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance. This is equal to the register number plus the width 353579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * (category) of the type used. Among other things, this may also 354579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * be used to determine the minimum required register count 355579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * implied by this instance. 356579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 357579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code >= 0;} the required registers size 358579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 359579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int getNextReg() { 360579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return reg + getCategory(); 361579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 362579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 363579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 364579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the category of this instance's type. This is just a convenient 365579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * shorthand for {@code getType().getCategory()}. 366579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 367579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @see #isCategory1 368579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @see #isCategory2 369579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code 1..2;} the category of this instance's type 370579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 371579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int getCategory() { 372579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return type.getType().getCategory(); 373579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 374579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 375579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 376579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets whether this instance's type is category 1. This is just a 377579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * convenient shorthand for {@code getType().isCategory1()}. 378579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 379579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @see #getCategory 380579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @see #isCategory2 381579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return whether or not this instance's type is of category 1 382579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 383579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean isCategory1() { 384579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return type.getType().isCategory1(); 385579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 386579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 387579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 388579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets whether this instance's type is category 2. This is just a 389579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * convenient shorthand for {@code getType().isCategory2()}. 390579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 391579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @see #getCategory 392579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @see #isCategory1 393579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return whether or not this instance's type is of category 2 394579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 395579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean isCategory2() { 396579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return type.getType().isCategory2(); 397579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 398579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 399579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 400579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the string form for just the register number of this instance. 401579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 402579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the register string form 403579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 404579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String regString() { 405579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return regString(reg); 406579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 407579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 408579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 409579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns an instance that is the intersection between this instance 410579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * and the given one, if any. The intersection is defined as follows: 411579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 412579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <ul> 413579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <li>If {@code other} is {@code null}, then the result 414579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * is {@code null}. 415579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <li>If the register numbers don't match, then the intersection 416579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * is {@code null}. Otherwise, the register number of the 417579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * intersection is the same as the one in the two instances.</li> 418579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <li>If the types returned by {@code getType()} are not 419579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code equals()}, then the intersection is null.</li> 420579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <li>If the type bearers returned by {@code getTypeBearer()} 421579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * are {@code equals()}, then the intersection's type bearer 422579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * is the one from this instance. Otherwise, the intersection's 423579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * type bearer is the {@code getType()} of this instance.</li> 424579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * <li>If the locals are {@code equals()}, then the local info 425579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * of the intersection is the local info of this instance. Otherwise, 426579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the local info of the intersection is {@code null}.</li> 427579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * </ul> 428579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 429579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param other {@code null-ok;} instance to intersect with (or {@code null}) 430579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param localPrimary whether local variables are primary to the 431579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * intersection; if {@code true}, then the only non-null 432579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * results occur when registers being intersected have equal local 433579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * infos (or both have {@code null} local infos) 434579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code null-ok;} the intersection 435579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 436579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public RegisterSpec intersect(RegisterSpec other, boolean localPrimary) { 437579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (this == other) { 438579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Easy out. 439579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return this; 440579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 441579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 442579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if ((other == null) || (reg != other.getReg())) { 443579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return null; 444579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 445579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 446579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson LocalItem resultLocal = 447579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ((local == null) || !local.equals(other.getLocalItem())) 448579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ? null : local; 449579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson boolean sameName = (resultLocal == local); 450579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 451579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (localPrimary && !sameName) { 452579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return null; 453579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 454579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 455579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Type thisType = getType(); 456579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Type otherType = other.getType(); 457579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 458579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Note: Types are always interned. 459579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (thisType != otherType) { 460579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return null; 461579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 462579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 463579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson TypeBearer resultTypeBearer = 464579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson type.equals(other.getTypeBearer()) ? type : thisType; 465579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 466579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if ((resultTypeBearer == type) && sameName) { 467579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // It turns out that the intersection is "this" after all. 468579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return this; 469579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 470579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 471579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return (resultLocal == null) ? make(reg, resultTypeBearer) : 472579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson make(reg, resultTypeBearer, resultLocal); 473579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 474579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 475579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 476579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns an instance that is identical to this one, except that the 477579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * register number is replaced by the given one. 478579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 479579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param newReg {@code >= 0;} the new register number 480579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} an appropriately-constructed instance 481579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 482579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public RegisterSpec withReg(int newReg) { 483579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (reg == newReg) { 484579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return this; 485579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 486579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 487579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return makeLocalOptional(newReg, type, local); 488579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 489579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 490579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 491579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns an instance that is identical to this one, except that 492579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the type is replaced by the given one. 493579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 494579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param newType {@code non-null;} the new type 495579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} an appropriately-constructed instance 496579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 497579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public RegisterSpec withType(TypeBearer newType) { 498579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return makeLocalOptional(reg, newType, local); 499579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 500579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 501579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 502579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns an instance that is identical to this one, except that the 503579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * register number is offset by the given amount. 504579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 505579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param delta the amount to offset the register number by 506579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} an appropriately-constructed instance 507579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 508579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public RegisterSpec withOffset(int delta) { 509579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (delta == 0) { 510579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return this; 511579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 512579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 513579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return withReg(reg + delta); 514579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 515579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 516579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 517579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns an instance that is identical to this one, except that 518579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the type bearer is replaced by the actual underlying type 519579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * (thereby stripping off non-type information) with any 520579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * initialization information stripped away as well. 521579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 522579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} an appropriately-constructed instance 523579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 524579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public RegisterSpec withSimpleType() { 525579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson TypeBearer orig = type; 526579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Type newType; 527579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 528579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (orig instanceof Type) { 529579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson newType = (Type) orig; 530579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 531579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson newType = orig.getType(); 532579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 533579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 534579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (newType.isUninitialized()) { 535579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson newType = newType.getInitializedType(); 536579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 537579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 538579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (newType == orig) { 539579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return this; 540579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 541579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 542579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return makeLocalOptional(reg, newType, local); 543579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 544579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 545579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 546579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns an instance that is identical to this one except that the 547579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * local variable is as specified in the parameter. 548579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 549579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param local {@code null-ok;} the local item or null for none 550579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return an appropriate instance 551579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 552579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public RegisterSpec withLocalItem(LocalItem local) { 553579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if ((this.local== local) 554579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson || ((this.local != null) && this.local.equals(local))) { 555579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 556579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return this; 557579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 558579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 559579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return makeLocalOptional(reg, type, local); 560579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 561579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 562579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 563579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 564579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Helper for {@link #toString} and {@link #toHuman}. 565579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 566579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param human whether to be human-oriented 567579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the string form 568579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 569579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private String toString0(boolean human) { 570579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson StringBuffer sb = new StringBuffer(40); 571579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 572579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(regString()); 573579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(":"); 574579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 575579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (local != null) { 576579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(local.toString()); 577579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 578579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 579579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Type justType = type.getType(); 580579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(justType); 581579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 582579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (justType != type) { 583579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append("="); 584579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (human && (type instanceof CstString)) { 585579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(((CstString) type).toQuoted()); 586579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else if (human && (type instanceof Constant)) { 587579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(type.toHuman()); 588579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 589579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(type); 590579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 591579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 592579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 593579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return sb.toString(); 594579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 595579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 596579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 597579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Holder of register spec data for the purposes of comparison (so that 598579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code RegisterSpec} itself can still keep {@code final} 599579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * instance variables. 600579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 601579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static class ForComparison { 602579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code >= 0;} register number */ 603579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private int reg; 604579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 605579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} type loaded or stored */ 606579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private TypeBearer type; 607579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 608579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 609579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code null-ok;} local variable associated with this 610579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * register, if any 611579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 612579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private LocalItem local; 613579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 614579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 615579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Set all the instance variables. 616579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 617579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param reg {@code >= 0;} the register number 618579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param type {@code non-null;} the type (or possibly actual 619579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * value) which is loaded from or stored to the indicated 620579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * register 621579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param local {@code null-ok;} the associated local variable, if any 622579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} an appropriately-constructed instance 623579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 624579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void set(int reg, TypeBearer type, LocalItem local) { 625579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.reg = reg; 626579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.type = type; 627579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.local = local; 628579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 629579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 630579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 631579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Construct a {@code RegisterSpec} of this instance's 632579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * contents. 633579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 634579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} an appropriately-constructed instance 635579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 636579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public RegisterSpec toRegisterSpec() { 637579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return new RegisterSpec(reg, type, local); 638579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 639579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 640579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 641579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 642579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean equals(Object other) { 643579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (!(other instanceof RegisterSpec)) { 644579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; 645579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 646579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 647579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec spec = (RegisterSpec) other; 648579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return spec.equals(reg, type, local); 649579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 650579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 651579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 652579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 653579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int hashCode() { 654579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return hashCodeOf(reg, type, local); 655579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 656579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 657579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 658