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.CstUtf8; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.MutabilityControl; 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Set of {@link RegisterSpec} instances, where a given register number 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * may appear only once in the set. 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class RegisterSpecSet 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul extends MutabilityControl { 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} no-element instance */ 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static final RegisterSpecSet EMPTY = new RegisterSpecSet(0); 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code non-null;} array of register specs, where each element is 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null} or is an instance whose {@code reg} 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * matches the array index 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final RegisterSpec[] specs; 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= -1;} size of the set or {@code -1} if not yet calculated */ 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int size; 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. The instance is initially empty. 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param maxSize {@code >= 0;} the maximum register number (exclusive) that 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * may be represented in this instance 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public RegisterSpecSet(int maxSize) { 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul super(maxSize != 0); 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.specs = new RegisterSpec[maxSize]; 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.size = 0; 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean equals(Object other) { 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!(other instanceof RegisterSpecSet)) { 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecSet otherSet = (RegisterSpecSet) other; 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec[] otherSpecs = otherSet.specs; 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int len = specs.length; 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((len != otherSpecs.length) || (size() != otherSet.size())) { 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < len; i++) { 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec s1 = specs[i]; 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec s2 = otherSpecs[i]; 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (s1 == s2) { 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul continue; 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((s1 == null) || !s1.equals(s2)) { 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return true; 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int hashCode() { 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int len = specs.length; 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int hash = 0; 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < len; i++) { 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec spec = specs[i]; 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int oneHash = (spec == null) ? 0 : spec.hashCode(); 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul hash = (hash * 31) + oneHash; 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return hash; 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public String toString() { 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int len = specs.length; 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuffer sb = new StringBuffer(len * 25); 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append('{'); 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul boolean any = false; 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < len; i++) { 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec spec = specs[i]; 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (spec != null) { 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (any) { 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(", "); 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul any = true; 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(spec); 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append('}'); 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the maximum number of registers that may be in this instance, which 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * is also the maximum-plus-one of register numbers that may be 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * represented. 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the maximum size 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int getMaxSize() { 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return specs.length; 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the current size of this instance. 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code >= 0;} the size 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int size() { 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int result = size; 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (result < 0) { 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int len = specs.length; 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result = 0; 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < len; i++) { 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (specs[i] != null) { 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result++; 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul size = result; 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the element with the given register number, if any. 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param reg {@code >= 0;} the desired register number 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} the element with the given register number or 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null} if there is none 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public RegisterSpec get(int reg) { 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul try { 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return specs[reg]; 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } catch (ArrayIndexOutOfBoundsException ex) { 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Translate the exception. 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("bogus reg"); 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the element with the same register number as the given 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * spec, if any. This is just a convenient shorthand for 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code get(spec.getReg())}. 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param spec {@code non-null;} spec with the desired register number 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} the element with the matching register number or 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code null} if there is none 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public RegisterSpec get(RegisterSpec spec) { 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return get(spec.getReg()); 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns the spec in this set that's currently associated with a 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * given local (type, name, and signature), or {@code null} if there is 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * none. This ignores the register number of the given spec but 193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * matches on everything else. 194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param spec {@code non-null;} local to look for 196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} first register found that matches, if any 197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public RegisterSpec findMatchingLocal(RegisterSpec spec) { 199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int length = specs.length; 200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int reg = 0; reg < length; reg++) { 202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec s = specs[reg]; 203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (s == null) { 205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul continue; 206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (spec.matchesVariable(s)) { 209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return s; 210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns the spec in this set that's currently associated with a given 218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * local (name and signature), or {@code null} if there is none. 219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param local {@code non-null;} local item to search for 221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code null-ok;} first register found with matching name and signature 222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public RegisterSpec localItemToSpec(LocalItem local) { 224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int length = specs.length; 225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int reg = 0; reg < length; reg++) { 227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec spec = specs[reg]; 228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((spec != null) && local.equals(spec.getLocalItem())) { 230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return spec; 231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return null; 235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Removes a spec from the set. Only the register number 239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * of the parameter is significant. 240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param toRemove {@code non-null;} register to remove. 242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void remove(RegisterSpec toRemove) { 244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul try { 245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul specs[toRemove.getReg()] = null; 246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul size = -1; 247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } catch (ArrayIndexOutOfBoundsException ex) { 248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Translate the exception. 249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("bogus reg"); 250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Puts the given spec into the set. If there is already an element in 255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the set with the same register number, it is replaced. Additionally, 256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * if the previous element is for a category-2 register, then that 257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * previous element is nullified. Finally, if the given spec is for 258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * a category-2 register, then the immediately subsequent element 259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * is nullified. 260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param spec {@code non-null;} the register spec to put in the instance 262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void put(RegisterSpec spec) { 264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throwIfImmutable(); 265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (spec == null) { 267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("spec == null"); 268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul size = -1; 271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul try { 273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int reg = spec.getReg(); 274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul specs[reg] = spec; 275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (reg > 0) { 277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int prevReg = reg - 1; 278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec prevSpec = specs[prevReg]; 279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((prevSpec != null) && (prevSpec.getCategory() == 2)) { 280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul specs[prevReg] = null; 281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (spec.getCategory() == 2) { 285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul specs[reg + 1] = null; 286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } catch (ArrayIndexOutOfBoundsException ex) { 288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Translate the exception. 289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("spec.getReg() out of range"); 290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Put the entire contents of the given set into this one. 295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param set {@code non-null;} the set to put into this instance 297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void putAll(RegisterSpecSet set) { 299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int max = set.getMaxSize(); 300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < max; i++) { 302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec spec = set.get(i); 303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (spec != null) { 304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul put(spec); 305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Intersects this instance with the given one, modifying this 311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * instance. The intersection consists of the pairwise 312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@link RegisterSpec#intersect} of corresponding elements from 313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * this instance and the given one where both are non-null. 314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param other {@code non-null;} set to intersect with 316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param localPrimary whether local variables are primary to 317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * the intersection; if {@code true}, then the only non-null 318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * result elements occur when registers being intersected have 319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * equal names (or both have {@code null} names) 320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void intersect(RegisterSpecSet other, boolean localPrimary) { 322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throwIfImmutable(); 323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec[] otherSpecs = other.specs; 325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int thisLen = specs.length; 326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int len = Math.min(thisLen, otherSpecs.length); 327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul size = -1; 329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < len; i++) { 331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec spec = specs[i]; 332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (spec == null) { 334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul continue; 335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec intersection = 338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul spec.intersect(otherSpecs[i], localPrimary); 339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (intersection != spec) { 340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul specs[i] = intersection; 341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = len; i < thisLen; i++) { 345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul specs[i] = null; 346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns an instance that is identical to this one, except that 351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * all register numbers are offset by the given amount. Mutability 352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * of the result is inherited from the original. 353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param delta the amount to offset the register numbers by 355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public RegisterSpecSet withOffset(int delta) { 358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int len = specs.length; 359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecSet result = new RegisterSpecSet(len + delta); 360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < len; i++) { 362917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec spec = specs[i]; 363917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (spec != null) { 364917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result.put(spec.withOffset(delta)); 365917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 366917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 367917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 368917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result.size = size; 369917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 370917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (isImmutable()) { 371917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result.setImmutable(); 372917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 373917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 374917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 375917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 376917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 377917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 378917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Makes and return a mutable copy of this instance. 379917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 380917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the mutable copy 381917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 382917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public RegisterSpecSet mutableCopy() { 383917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int len = specs.length; 384917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpecSet copy = new RegisterSpecSet(len); 385917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 386917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < len; i++) { 387917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul RegisterSpec spec = specs[i]; 388917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (spec != null) { 389917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul copy.put(spec); 390917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 391917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 392917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 393917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul copy.size = size; 394917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 395917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return copy; 396917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 397917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 398