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.Type; 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.TypeBearer; 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.ToHuman; 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.HashMap; 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Combination of a register number and a type, used as the sources and 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * destinations of register-based operations. 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class RegisterSpec 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul implements TypeBearer, ToHuman, Comparable<RegisterSpec> { 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} string to prefix register numbers with */ 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static final String PREFIX = "v"; 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} intern table for instances */ 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static final HashMap<Object, RegisterSpec> theInterns = 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul new HashMap<Object, RegisterSpec>(1000); 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} common comparison instance used while interning */ 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static final ForComparison theInterningItem = new ForComparison(); 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= 0;} register number */ 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final int reg; 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} type loaded or stored */ 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final TypeBearer type; 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code null-ok;} local variable info associated with this register, if any */ 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final LocalItem local; 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Intern the given triple as an instance of this class. 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param reg {@code >= 0;} the register number 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param type {@code non-null;} the type (or possibly actual value) which 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * is loaded from or stored to the indicated register 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param local {@code null-ok;} the associated local variable, if any 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static RegisterSpec intern(int reg, TypeBearer type, 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul LocalItem local) { 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul theInterningItem.set(reg, type, local); 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec found = theInterns.get(theInterningItem); 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (found != null) { 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return found; 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul found = theInterningItem.toRegisterSpec(); 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul theInterns.put(found, found); 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return found; 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an instance for the given register number and type, with 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * no variable info. This method is allowed to return shared 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instances (but doesn't necessarily do so). 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param reg {@code >= 0;} the register number 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param type {@code non-null;} the type (or possibly actual value) which 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * is loaded from or stored to the indicated register 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static RegisterSpec make(int reg, TypeBearer type) { 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return intern(reg, type, null); 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an instance for the given register number, type, and 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * variable info. This method is allowed to return shared 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instances (but doesn't necessarily do so). 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param reg {@code >= 0;} the register number 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param type {@code non-null;} the type (or possibly actual value) which 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * is loaded from or stored to the indicated register 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param local {@code non-null;} the associated local variable 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static RegisterSpec make(int reg, TypeBearer type, 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul LocalItem local) { 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (local == null) { 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("local == null"); 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return intern(reg, type, local); 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an instance for the given register number, type, and 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * variable info. This method is allowed to return shared 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instances (but doesn't necessarily do so). 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param reg {@code >= 0;} the register number 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param type {@code non-null;} the type (or possibly actual value) which 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * is loaded from or stored to the indicated register 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param local {@code null-ok;} the associated variable info or null for 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * none 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static RegisterSpec makeLocalOptional( 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int reg, TypeBearer type, LocalItem local) { 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return intern(reg, type, local); 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the string form for the given register number. 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param reg {@code >= 0;} the register number 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the string form 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static String regString(int reg) { 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return PREFIX + reg; 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. This constructor is private. Use 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@link #make}. 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param reg {@code >= 0;} the register number 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param type {@code non-null;} the type (or possibly actual value) which 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * is loaded from or stored to the indicated register 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param local {@code null-ok;} the associated local variable, if any 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private RegisterSpec(int reg, TypeBearer type, LocalItem local) { 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (reg < 0) { 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("reg < 0"); 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (type == null) { 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("type == null"); 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.reg = reg; 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.type = type; 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.local = local; 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean equals(Object other) { 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!(other instanceof RegisterSpec)) { 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (other instanceof ForComparison) { 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ForComparison fc = (ForComparison) other; 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return equals(fc.reg, fc.type, fc.local); 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec spec = (RegisterSpec) other; 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return equals(spec.reg, spec.type, spec.local); 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Like {@code equals}, but only consider the simple types of the 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * registers. That is, this compares {@code getType()} on the types 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * to ignore whatever arbitrary extra stuff might be carried around 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * by an outer {@link TypeBearer}. 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param other {@code null-ok;} spec to compare to 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff {@code this} and {@code other} are equal 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * in the stated way 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean equalsUsingSimpleType(RegisterSpec other) { 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!matchesVariable(other)) { 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (reg == other.reg); 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Like {@link #equalsUsingSimpleType} but ignoring the register number. 195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * This is useful to determine if two instances refer to the "same" 196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * local variable. 197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param other {@code null-ok;} spec to compare to 199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code true} iff {@code this} and {@code other} are equal 200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * in the stated way 201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean matchesVariable(RegisterSpec other) { 203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (other == null) { 204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return type.getType().equals(other.type.getType()) 208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && ((local == other.local) 209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul || ((local != null) && local.equals(other.local))); 210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper for {@link #equals} and {@link #ForComparison.equals}, 214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * which actually does the test. 215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param reg value of the instance variable, for another instance 217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param type value of the instance variable, for another instance 218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param local value of the instance variable, for another instance 219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return whether this instance is equal to one with the given 220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * values 221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private boolean equals(int reg, TypeBearer type, LocalItem local) { 223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (this.reg == reg) 224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && this.type.equals(type) 225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul && ((this.local == local) 226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul || ((this.local != null) && this.local.equals(local))); 227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Compares by (in priority order) register number, unwrapped type 231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * (that is types not {@link TypeBearer}s, and local info. 232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param other {@code non-null;} spec to compare to 234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code -1..1;} standard result of comparison 235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int compareTo(RegisterSpec other) { 237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (this.reg < other.reg) { 238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return -1; 239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else if (this.reg > other.reg) { 240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return 1; 241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int compare = type.getType().compareTo(other.type.getType()); 244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (compare != 0) { 246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return compare; 247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (this.local == null) { 250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (other.local == null) ? 0 : -1; 251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else if (other.local == null) { 252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return 1; 253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return this.local.compareTo(other.local); 256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int hashCode() { 261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return hashCodeOf(reg, type, local); 262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper for {@link #hashCode} and {@link #ForComparison.hashCode}, 266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * which actually does the calculation. 267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param reg value of the instance variable 269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param type value of the instance variable 270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param local value of the instance variable 271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return the hash code 272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static int hashCodeOf(int reg, TypeBearer type, LocalItem local) { 274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int hash = (local != null) ? local.hashCode() : 0; 275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul hash = (hash * 31 + type.hashCode()) * 31 + reg; 277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return hash; 278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public String toString() { 283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return toString0(false); 284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public String toHuman() { 288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return toString0(true); 289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public Type getType() { 293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return type.getType(); 294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public TypeBearer getFrameType() { 298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return type.getFrameType(); 299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final int getBasicType() { 303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return type.getBasicType(); 304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final int getBasicFrameType() { 308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return type.getBasicFrameType(); 309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final boolean isConstant() { 313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the register number. 318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the register number 320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getReg() { 322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return reg; 323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the type (or actual value) which is loaded from or stored 327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * to the register associated with this instance. 328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the type 330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public TypeBearer getTypeBearer() { 332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return type; 333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the variable info associated with this instance, if any. 337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} the variable info, or {@code null} if this 339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance has none 340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public LocalItem getLocalItem() { 342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return local; 343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the next available register number after the one in this 347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance. This is equal to the register number plus the width 348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * (category) of the type used. Among other things, this may also 349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * be used to determine the minimum required register count 350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * implied by this instance. 351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the required registers size 353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getNextReg() { 355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return reg + getCategory(); 356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the category of this instance's type. This is just a convenient 360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * shorthand for {@code getType().getCategory()}. 361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 362917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @see #isCategory1 363917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @see #isCategory2 364917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code 1..2;} the category of this instance's type 365917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 366917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getCategory() { 367917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return type.getType().getCategory(); 368917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 369917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 370917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 371917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets whether this instance's type is category 1. This is just a 372917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * convenient shorthand for {@code getType().isCategory1()}. 373917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 374917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @see #getCategory 375917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @see #isCategory2 376917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return whether or not this instance's type is of category 1 377917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 378917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean isCategory1() { 379917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return type.getType().isCategory1(); 380917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 381917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 382917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 383917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets whether this instance's type is category 2. This is just a 384917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * convenient shorthand for {@code getType().isCategory2()}. 385917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 386917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @see #getCategory 387917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @see #isCategory1 388917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return whether or not this instance's type is of category 2 389917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 390917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean isCategory2() { 391917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return type.getType().isCategory2(); 392917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 393917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 394917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 395917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the string form for just the register number of this instance. 396917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 397917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the register string form 398917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 399917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public String regString() { 400917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return regString(reg); 401917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 402917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 403917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 404917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an instance that is the intersection between this instance 405917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * and the given one, if any. The intersection is defined as follows: 406917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 407917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <ul> 408917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <li>If {@code other} is {@code null}, then the result 409917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * is {@code null}. 410917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <li>If the register numbers don't match, then the intersection 411917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * is {@code null}. Otherwise, the register number of the 412917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * intersection is the same as the one in the two instances.</li> 413917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <li>If the types returned by {@code getType()} are not 414917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code equals()}, then the intersection is null.</li> 415917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <li>If the type bearers returned by {@code getTypeBearer()} 416917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * are {@code equals()}, then the intersection's type bearer 417917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * is the one from this instance. Otherwise, the intersection's 418917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * type bearer is the {@code getType()} of this instance.</li> 419917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * <li>If the locals are {@code equals()}, then the local info 420917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * of the intersection is the local info of this instance. Otherwise, 421917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the local info of the intersection is {@code null}.</li> 422917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * </ul> 423917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 424917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param other {@code null-ok;} instance to intersect with (or {@code null}) 425917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param localPrimary whether local variables are primary to the 426917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * intersection; if {@code true}, then the only non-null 427917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * results occur when registers being intersected have equal local 428917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * infos (or both have {@code null} local infos) 429917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} the intersection 430917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 431917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public RegisterSpec intersect(RegisterSpec other, boolean localPrimary) { 432917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (this == other) { 433917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Easy out. 434917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return this; 435917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 436917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 437917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((other == null) || (reg != other.getReg())) { 438917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 439917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 440917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 441917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul LocalItem resultLocal = 442917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ((local == null) || !local.equals(other.getLocalItem())) 443917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul ? null : local; 444917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul boolean sameName = (resultLocal == local); 445917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 446917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (localPrimary && !sameName) { 447917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 448917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 449917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 450917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Type thisType = getType(); 451917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Type otherType = other.getType(); 452917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 453917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Note: Types are always interned. 454917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (thisType != otherType) { 455917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 456917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 457917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 458917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul TypeBearer resultTypeBearer = 459917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul type.equals(other.getTypeBearer()) ? type : thisType; 460917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 461917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((resultTypeBearer == type) && sameName) { 462917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // It turns out that the intersection is "this" after all. 463917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return this; 464917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 465917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 466917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return (resultLocal == null) ? make(reg, resultTypeBearer) : 467917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul make(reg, resultTypeBearer, resultLocal); 468917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 469917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 470917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 471917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an instance that is identical to this one, except that the 472917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * register number is replaced by the given one. 473917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 474917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param newReg {@code >= 0;} the new register number 475917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 476917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 477917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public RegisterSpec withReg(int newReg) { 478917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (reg == newReg) { 479917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return this; 480917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 481917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 482917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return makeLocalOptional(newReg, type, local); 483917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 484917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 485917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 486917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an instance that is identical to this one, except that 487917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the type is replaced by the given one. 488917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 489917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param newType {@code non-null;} the new type 490917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 491917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 492917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public RegisterSpec withType(TypeBearer newType) { 493917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return makeLocalOptional(reg, newType, local); 494917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 495917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 496917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 497917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an instance that is identical to this one, except that the 498917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * register number is offset by the given amount. 499917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 500917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param delta the amount to offset the register number by 501917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 502917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 503917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public RegisterSpec withOffset(int delta) { 504917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (delta == 0) { 505917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return this; 506917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 507917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 508917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return withReg(reg + delta); 509917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 510917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 511917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 512917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an instance that is identical to this one, except that 513917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the type bearer is replaced by the actual underlying type 514917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * (thereby stripping off non-type information) with any 515917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * initialization information stripped away as well. 516917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 517917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 518917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 519917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public RegisterSpec withSimpleType() { 520917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul TypeBearer orig = type; 521917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Type newType; 522917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 523917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (orig instanceof Type) { 524917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul newType = (Type) orig; 525917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 526917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul newType = orig.getType(); 527917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 528917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 529917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (newType.isUninitialized()) { 530917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul newType = newType.getInitializedType(); 531917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 532917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 533917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (newType == orig) { 534917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return this; 535917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 536917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 537917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return makeLocalOptional(reg, newType, local); 538917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 539917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 540917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 541917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an instance that is identical to this one except that the 542917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * local variable is as specified in the parameter. 543917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 544917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param local {@code null-ok;} the local item or null for none 545917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return an appropriate instance 546917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 547917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public RegisterSpec withLocalItem(LocalItem local) { 548917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((this.local== local) 549917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul || ((this.local != null) && this.local.equals(local))) { 550917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 551917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return this; 552917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 553917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 554917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return makeLocalOptional(reg, type, local); 555917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 556917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 557917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 558917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 559917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper for {@link #toString} and {@link #toHuman}. 560917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 561917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param human whether to be human-oriented 562917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the string form 563917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 564917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private String toString0(boolean human) { 565917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuffer sb = new StringBuffer(40); 566917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 567917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(regString()); 568917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(":"); 569917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 570917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (local != null) { 571917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(local.toString()); 572917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 573917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 574917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Type justType = type.getType(); 575917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(justType); 576917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 577917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (justType != type) { 578917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append("="); 579917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (human && (type instanceof Constant)) { 580917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(((Constant) type).toHuman()); 581917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 582917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(type); 583917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 584917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 585917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 586917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 587917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 588917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 589917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 590917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Holder of register spec data for the purposes of comparison (so that 591917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code RegisterSpec} itself can still keep {@code final} 592917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance variables. 593917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 594917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static class ForComparison { 595917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= 0;} register number */ 596917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int reg; 597917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 598917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} type loaded or stored */ 599917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private TypeBearer type; 600917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 601917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 602917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null-ok;} local variable associated with this 603917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * register, if any 604917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 605917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private LocalItem local; 606917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 607917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 608917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Set all the instance variables. 609917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 610917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param reg {@code >= 0;} the register number 611917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param type {@code non-null;} the type (or possibly actual 612917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * value) which is loaded from or stored to the indicated 613917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * register 614917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param local {@code null-ok;} the associated local variable, if any 615917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 616917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 617917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void set(int reg, TypeBearer type, LocalItem local) { 618917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.reg = reg; 619917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.type = type; 620917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.local = local; 621917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 622917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 623917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 624917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Construct a {@code RegisterSpec} of this instance's 625917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * contents. 626917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 627917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 628917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 629917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public RegisterSpec toRegisterSpec() { 630917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return new RegisterSpec(reg, type, local); 631917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 632917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 633917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 634917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 635917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean equals(Object other) { 636917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!(other instanceof RegisterSpec)) { 637917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 638917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 639917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 640917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec spec = (RegisterSpec) other; 641917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return spec.equals(reg, type, local); 642917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 643917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 644917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 645917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 646917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int hashCode() { 647917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return hashCodeOf(reg, type, local); 648917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 649917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 650917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 651