diff options
Diffstat (limited to 'dx/src/com/android/dx/rop/code/RegisterSpecList.java')
-rw-r--r-- | dx/src/com/android/dx/rop/code/RegisterSpecList.java | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/dx/src/com/android/dx/rop/code/RegisterSpecList.java b/dx/src/com/android/dx/rop/code/RegisterSpecList.java new file mode 100644 index 0000000..3d891fd --- /dev/null +++ b/dx/src/com/android/dx/rop/code/RegisterSpecList.java @@ -0,0 +1,409 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.dx.rop.code; + +import com.android.dx.rop.type.Type; +import com.android.dx.rop.type.TypeList; +import com.android.dx.util.FixedSizeList; + +import java.util.BitSet; + +/** + * List of {@link RegisterSpec} instances. + */ +public final class RegisterSpecList + extends FixedSizeList implements TypeList { + /** {@code non-null;} no-element instance */ + public static final RegisterSpecList EMPTY = new RegisterSpecList(0); + + /** + * Makes a single-element instance. + * + * @param spec {@code non-null;} the element + * @return {@code non-null;} an appropriately-constructed instance + */ + public static RegisterSpecList make(RegisterSpec spec) { + RegisterSpecList result = new RegisterSpecList(1); + result.set(0, spec); + return result; + } + + /** + * Makes a two-element instance. + * + * @param spec0 {@code non-null;} the first element + * @param spec1 {@code non-null;} the second element + * @return {@code non-null;} an appropriately-constructed instance + */ + public static RegisterSpecList make(RegisterSpec spec0, + RegisterSpec spec1) { + RegisterSpecList result = new RegisterSpecList(2); + result.set(0, spec0); + result.set(1, spec1); + return result; + } + + /** + * Makes a three-element instance. + * + * @param spec0 {@code non-null;} the first element + * @param spec1 {@code non-null;} the second element + * @param spec2 {@code non-null;} the third element + * @return {@code non-null;} an appropriately-constructed instance + */ + public static RegisterSpecList make(RegisterSpec spec0, RegisterSpec spec1, + RegisterSpec spec2) { + RegisterSpecList result = new RegisterSpecList(3); + result.set(0, spec0); + result.set(1, spec1); + result.set(2, spec2); + return result; + } + + /** + * Makes a four-element instance. + * + * @param spec0 {@code non-null;} the first element + * @param spec1 {@code non-null;} the second element + * @param spec2 {@code non-null;} the third element + * @param spec3 {@code non-null;} the fourth element + * @return {@code non-null;} an appropriately-constructed instance + */ + public static RegisterSpecList make(RegisterSpec spec0, RegisterSpec spec1, + RegisterSpec spec2, + RegisterSpec spec3) { + RegisterSpecList result = new RegisterSpecList(4); + result.set(0, spec0); + result.set(1, spec1); + result.set(2, spec2); + result.set(3, spec3); + return result; + } + + /** + * Constructs an instance. All indices initially contain {@code null}. + * + * @param size the size of the list + */ + public RegisterSpecList(int size) { + super(size); + } + + /** {@inheritDoc} */ + public Type getType(int n) { + return get(n).getType().getType(); + } + + /** {@inheritDoc} */ + public int getWordCount() { + int sz = size(); + int result = 0; + + for (int i = 0; i < sz; i++) { + result += getType(i).getCategory(); + } + + return result; + } + + /** {@inheritDoc} */ + public TypeList withAddedType(Type type) { + throw new UnsupportedOperationException("unsupported"); + } + + /** + * Gets the indicated element. It is an error to call this with the + * index for an element which was never set; if you do that, this + * will throw {@code NullPointerException}. + * + * @param n {@code >= 0, < size();} which element + * @return {@code non-null;} the indicated element + */ + public RegisterSpec get(int n) { + return (RegisterSpec) get0(n); + } + + /** + * Returns a RegisterSpec in this list that uses the specified register, + * or null if there is none in this list. + * @param reg Register to find + * @return RegisterSpec that uses argument or null. + */ + public RegisterSpec specForRegister(int reg) { + int sz = size(); + for (int i = 0; i < sz; i++) { + RegisterSpec rs; + + rs = get(i); + + if (rs.getReg() == reg) { + return rs; + } + } + + return null; + } + + /** + * Returns the index of a RegisterSpec in this list that uses the specified + * register, or -1 if none in this list uses the register. + * @param reg Register to find + * @return index of RegisterSpec or -1 + */ + public int indexOfRegister(int reg) { + int sz = size(); + for (int i = 0; i < sz; i++) { + RegisterSpec rs; + + rs = get(i); + + if (rs.getReg() == reg) { + return i; + } + } + + return -1; + } + + /** + * Sets the element at the given index. + * + * @param n {@code >= 0, < size();} which element + * @param spec {@code non-null;} the value to store + */ + public void set(int n, RegisterSpec spec) { + set0(n, spec); + } + + /** + * Gets the minimum required register count implied by this + * instance. This is equal to the highest register number referred + * to plus the widest width (largest category) of the type used in + * that register. + * + * @return {@code >= 0;} the required registers size + */ + public int getRegistersSize() { + int sz = size(); + int result = 0; + + for (int i = 0; i < sz; i++) { + RegisterSpec spec = (RegisterSpec) get0(i); + if (spec != null) { + int min = spec.getNextReg(); + if (min > result) { + result = min; + } + } + } + + return result; + } + + /** + * Returns a new instance, which is the same as this instance, + * except that it has an additional element prepended to the original. + * Mutability of the result is inherited from the original. + * + * @param spec {@code non-null;} the new first spec (to prepend) + * @return {@code non-null;} an appropriately-constructed instance + */ + public RegisterSpecList withFirst(RegisterSpec spec) { + int sz = size(); + RegisterSpecList result = new RegisterSpecList(sz + 1); + + for (int i = 0; i < sz; i++) { + result.set0(i + 1, get0(i)); + } + + result.set0(0, spec); + if (isImmutable()) { + result.setImmutable(); + } + + return result; + } + + /** + * Returns a new instance, which is the same as this instance, + * except that its first element is removed. Mutability of the + * result is inherited from the original. + * + * @return {@code non-null;} an appropriately-constructed instance + */ + public RegisterSpecList withoutFirst() { + int newSize = size() - 1; + + if (newSize == 0) { + return EMPTY; + } + + RegisterSpecList result = new RegisterSpecList(newSize); + + for (int i = 0; i < newSize; i++) { + result.set0(i, get0(i + 1)); + } + + if (isImmutable()) { + result.setImmutable(); + } + + return result; + } + + /** + * Returns a new instance, which is the same as this instance, + * except that its last element is removed. Mutability of the + * result is inherited from the original. + * + * @return {@code non-null;} an appropriately-constructed instance + */ + public RegisterSpecList withoutLast() { + int newSize = size() - 1; + + if (newSize == 0) { + return EMPTY; + } + + RegisterSpecList result = new RegisterSpecList(newSize); + + for (int i = 0; i < newSize; i++) { + result.set0(i, get0(i)); + } + + if (isImmutable()) { + result.setImmutable(); + } + + return result; + } + + /** + * Returns a new instance, which contains a subset of the elements + * specified by the given BitSet. Indexes in the BitSet with a zero + * are included, while indexes with a one are excluded. Mutability + * of the result is inherited from the original. + * + * @param exclusionSet {@code non-null;} set of registers to exclude + * @return {@code non-null;} an appropriately-constructed instance + */ + public RegisterSpecList subset(BitSet exclusionSet) { + int newSize = size() - exclusionSet.cardinality(); + + if (newSize == 0) { + return EMPTY; + } + + RegisterSpecList result = new RegisterSpecList(newSize); + + int newIndex = 0; + for (int oldIndex = 0; oldIndex < size(); oldIndex++) { + if (!exclusionSet.get(oldIndex)) { + result.set0(newIndex, get0(oldIndex)); + newIndex++; + } + } + + if (isImmutable()) { + result.setImmutable(); + } + + return result; + } + + /** + * Returns an instance that is identical to this one, except that + * all register numbers are offset by the given amount. Mutability + * of the result is inherited from the original. + * + * @param delta the amount to offset the register numbers by + * @return {@code non-null;} an appropriately-constructed instance + */ + public RegisterSpecList withOffset(int delta) { + int sz = size(); + + if (sz == 0) { + // Don't bother making a new zero-element instance. + return this; + } + + RegisterSpecList result = new RegisterSpecList(sz); + + for (int i = 0; i < sz; i++) { + RegisterSpec one = (RegisterSpec) get0(i); + if (one != null) { + result.set0(i, one.withOffset(delta)); + } + } + + if (isImmutable()) { + result.setImmutable(); + } + + return result; + } + + /** + * Returns an instance that is identical to this one, except that + * all incompatible register numbers are renumbered sequentially from + * the given base, with the first number duplicated if indicated. If + * a null BitSet is given, it indicates all registers are compatible. + * + * @param base the base register number + * @param duplicateFirst whether to duplicate the first number + * @param compatRegs {@code null-ok;} either a {@code non-null} set of + * compatible registers, or {@code null} to indicate all registers are + * compatible + * @return {@code non-null;} an appropriately-constructed instance + */ + public RegisterSpecList withExpandedRegisters(int base, + boolean duplicateFirst, + BitSet compatRegs) { + int sz = size(); + + if (sz == 0) { + // Don't bother making a new zero-element instance. + return this; + } + + RegisterSpecList result = new RegisterSpecList(sz); + + for (int i = 0; i < sz; i++) { + RegisterSpec one = (RegisterSpec) get0(i); + boolean replace = (compatRegs == null) ? true : !compatRegs.get(i); + + if (replace) { + result.set0(i, one.withReg(base)); + if (!duplicateFirst) { + base += one.getCategory(); + } + } else { + result.set0(i, one); + } + + if (duplicateFirst) { + duplicateFirst = false; + } + } + + if (isImmutable()) { + result.setImmutable(); + } + + return result; + } +} |