summaryrefslogtreecommitdiff
path: root/dx/src/com/android/dx/rop/code/RegisterSpecList.java
diff options
context:
space:
mode:
Diffstat (limited to 'dx/src/com/android/dx/rop/code/RegisterSpecList.java')
-rw-r--r--dx/src/com/android/dx/rop/code/RegisterSpecList.java409
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;
+ }
+}