diff options
Diffstat (limited to 'dx/src/com/android/dx/rop')
70 files changed, 0 insertions, 13836 deletions
diff --git a/dx/src/com/android/dx/rop/annotation/Annotation.java b/dx/src/com/android/dx/rop/annotation/Annotation.java deleted file mode 100644 index b7cf16494..000000000 --- a/dx/src/com/android/dx/rop/annotation/Annotation.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * 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.annotation; - -import com.android.dx.rop.cst.Constant; -import com.android.dx.rop.cst.CstAnnotation; -import com.android.dx.rop.cst.CstFieldRef; -import com.android.dx.rop.cst.CstLiteralBits; -import com.android.dx.rop.cst.CstMethodRef; -import com.android.dx.rop.cst.CstNat; -import com.android.dx.rop.cst.CstType; -import com.android.dx.rop.cst.CstUtf8; -import com.android.dx.rop.cst.TypedConstant; -import com.android.dx.util.Hex; -import com.android.dx.util.MutabilityControl; -import com.android.dx.util.ToHuman; - -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.TreeMap; - -/** - * An annotation on an element of a class. Annotations have an - * associated type and additionally consist of a set of (name, value) - * pairs, where the names are unique. - */ -public final class Annotation extends MutabilityControl - implements Comparable<Annotation>, ToHuman { - /** non-null; type of the annotation */ - private final CstType type; - - /** non-null; the visibility of the annotation */ - private final AnnotationVisibility visibility; - - /** non-null; map from names to {@link NameValuePair} instances */ - private final TreeMap<CstUtf8, NameValuePair> elements; - - /** - * Construct an instance. It initially contains no elements. - * - * @param type non-null; type of the annotation - * @param visibility non-null; the visibility of the annotation - */ - public Annotation(CstType type, AnnotationVisibility visibility) { - if (type == null) { - throw new NullPointerException("type == null"); - } - - if (visibility == null) { - throw new NullPointerException("visibility == null"); - } - - this.type = type; - this.visibility = visibility; - this.elements = new TreeMap<CstUtf8, NameValuePair>(); - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - if (! (other instanceof Annotation)) { - return false; - } - - Annotation otherAnnotation = (Annotation) other; - - if (! (type.equals(otherAnnotation.type) - && (visibility == otherAnnotation.visibility))) { - return false; - } - - return elements.equals(otherAnnotation.elements); - } - - /** {@inheritDoc} */ - public int hashCode() { - int hash = type.hashCode(); - hash = (hash * 31) + elements.hashCode(); - hash = (hash * 31) + visibility.hashCode(); - return hash; - } - - /** {@inheritDoc} */ - public int compareTo(Annotation other) { - int result = type.compareTo(other.type); - - if (result != 0) { - return result; - } - - result = visibility.compareTo(other.visibility); - - if (result != 0) { - return result; - } - - Iterator<NameValuePair> thisIter = elements.values().iterator(); - Iterator<NameValuePair> otherIter = other.elements.values().iterator(); - - while (thisIter.hasNext() && otherIter.hasNext()) { - NameValuePair thisOne = thisIter.next(); - NameValuePair otherOne = otherIter.next(); - - result = thisOne.compareTo(otherOne); - if (result != 0) { - return result; - } - } - - if (thisIter.hasNext()) { - return 1; - } else if (otherIter.hasNext()) { - return -1; - } - - return 0; - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return toHuman(); - } - - /** {@inheritDoc} */ - public String toHuman() { - StringBuilder sb = new StringBuilder(); - - sb.append(visibility.toHuman()); - sb.append("-annotation "); - sb.append(type.toHuman()); - sb.append(" {"); - - boolean first = true; - for (NameValuePair pair : elements.values()) { - if (first) { - first = false; - } else { - sb.append(", "); - } - sb.append(pair.getName().toHuman()); - sb.append(": "); - sb.append(pair.getValue().toHuman()); - } - - sb.append("}"); - return sb.toString(); - } - - /** - * Gets the type of this instance. - * - * @return non-null; the type - */ - public CstType getType() { - return type; - } - - /** - * Gets the visibility of this instance. - * - * @return non-null; the visibility - */ - public AnnotationVisibility getVisibility() { - return visibility; - } - - /** - * Put an element into the set of (name, value) pairs for this instance. - * If there is a preexisting element with the same name, it will be - * replaced by this method. - * - * @param pair non-null; the (name, value) pair to place into this instance - */ - public void put(NameValuePair pair) { - throwIfImmutable(); - - if (pair == null) { - throw new NullPointerException("pair == null"); - } - - elements.put(pair.getName(), pair); - } - - /** - * Add an element to the set of (name, value) pairs for this instance. - * It is an error to call this method if there is a preexisting element - * with the same name. - * - * @param pair non-null; the (name, value) pair to add to this instance - */ - public void add(NameValuePair pair) { - throwIfImmutable(); - - if (pair == null) { - throw new NullPointerException("pair == null"); - } - - CstUtf8 name = pair.getName(); - - if (elements.get(name) != null) { - throw new IllegalArgumentException("name already added: " + name); - } - - elements.put(name, pair); - } - - /** - * Gets the set of name-value pairs contained in this instance. The - * result is always unmodifiable. - * - * @return non-null; the set of name-value pairs - */ - public Collection<NameValuePair> getNameValuePairs() { - return Collections.unmodifiableCollection(elements.values()); - } -} diff --git a/dx/src/com/android/dx/rop/annotation/AnnotationVisibility.java b/dx/src/com/android/dx/rop/annotation/AnnotationVisibility.java deleted file mode 100644 index c53fcd804..000000000 --- a/dx/src/com/android/dx/rop/annotation/AnnotationVisibility.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2008 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.annotation; - -import com.android.dx.util.ToHuman; - -/** - * Visibility scope of an annotation. - */ -public enum AnnotationVisibility implements ToHuman { - RUNTIME("runtime"), - BUILD("build"), - SYSTEM("system"), - EMBEDDED("embedded"); - - /** non-null; the human-oriented string representation */ - private final String human; - - /** - * Constructs an instance. - * - * @param human non-null; the human-oriented string representation - */ - private AnnotationVisibility(String human) { - this.human = human; - } - - /** {@inheritDoc} */ - public String toHuman() { - return human; - } -} diff --git a/dx/src/com/android/dx/rop/annotation/Annotations.java b/dx/src/com/android/dx/rop/annotation/Annotations.java deleted file mode 100644 index c1da88364..000000000 --- a/dx/src/com/android/dx/rop/annotation/Annotations.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * 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.annotation; - -import com.android.dx.rop.cst.CstType; -import com.android.dx.util.MutabilityControl; - -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.TreeMap; - -/** - * List of {@link Annotation} instances. - */ -public final class Annotations extends MutabilityControl - implements Comparable<Annotations> { - /** non-null; immutable empty instance */ - public static final Annotations EMPTY = new Annotations(); - - static { - EMPTY.setImmutable(); - } - - /** non-null; map from types to annotations */ - private final TreeMap<CstType, Annotation> annotations; - - /** - * Constructs an immutable instance which is the combination of the - * two given instances. The two instances must contain disjoint sets - * of types. - * - * @param a1 non-null; an instance - * @param a2 non-null; the other instance - * @return non-null; the combination - * @throws IllegalArgumentException thrown if there is a duplicate type - */ - public static Annotations combine(Annotations a1, Annotations a2) { - Annotations result = new Annotations(); - - result.addAll(a1); - result.addAll(a2); - result.setImmutable(); - - return result; - } - - /** - * Constructs an immutable instance which is the combination of the - * given instance with the given additional annotation. The latter's - * type must not already appear in the former. - * - * @param annotations non-null; the instance to augment - * @param annotation non-null; the additional annotation - * @return non-null; the combination - * @throws IllegalArgumentException thrown if there is a duplicate type - */ - public static Annotations combine(Annotations annotations, - Annotation annotation) { - Annotations result = new Annotations(); - - result.addAll(annotations); - result.add(annotation); - result.setImmutable(); - - return result; - } - - /** - * Constructs an empty instance. - */ - public Annotations() { - annotations = new TreeMap<CstType, Annotation>(); - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - return annotations.hashCode(); - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - if (! (other instanceof Annotations)) { - return false; - } - - Annotations otherAnnotations = (Annotations) other; - - return annotations.equals(otherAnnotations.annotations); - } - - /** {@inheritDoc} */ - public int compareTo(Annotations other) { - Iterator<Annotation> thisIter = annotations.values().iterator(); - Iterator<Annotation> otherIter = other.annotations.values().iterator(); - - while (thisIter.hasNext() && otherIter.hasNext()) { - Annotation thisOne = thisIter.next(); - Annotation otherOne = otherIter.next(); - - int result = thisOne.compareTo(otherOne); - if (result != 0) { - return result; - } - } - - if (thisIter.hasNext()) { - return 1; - } else if (otherIter.hasNext()) { - return -1; - } - - return 0; - } - - /** {@inheritDoc} */ - public String toString() { - StringBuilder sb = new StringBuilder(); - boolean first = true; - - sb.append("annotations{"); - - for (Annotation a : annotations.values()) { - if (first) { - first = false; - } else { - sb.append(", "); - } - sb.append(a.toHuman()); - } - - sb.append("}"); - return sb.toString(); - } - - /** - * Gets the number of elements in this instance. - * - * @return >= 0; the size - */ - public int size() { - return annotations.size(); - } - - /** - * Adds an element to this instance. There must not already be an - * element of the same type. - * - * @param annotation non-null; the element to add - * @throws IllegalArgumentException thrown if there is a duplicate type - */ - public void add(Annotation annotation) { - throwIfImmutable(); - - if (annotation == null) { - throw new NullPointerException("annotation == null"); - } - - CstType type = annotation.getType(); - - if (annotations.containsKey(type)) { - throw new IllegalArgumentException("duplicate type: " + - type.toHuman()); - } - - annotations.put(type, annotation); - } - - /** - * Adds all of the elements of the given instance to this one. The - * instances must not have any duplicate types. - * - * @param toAdd non-null; the annotations to add - * @throws IllegalArgumentException thrown if there is a duplicate type - */ - public void addAll(Annotations toAdd) { - throwIfImmutable(); - - if (toAdd == null) { - throw new NullPointerException("toAdd == null"); - } - - for (Annotation a : toAdd.annotations.values()) { - add(a); - } - } - - /** - * Gets the set of annotations contained in this instance. The - * result is always unmodifiable. - * - * @return non-null; the set of annotations - */ - public Collection<Annotation> getAnnotations() { - return Collections.unmodifiableCollection(annotations.values()); - } -} diff --git a/dx/src/com/android/dx/rop/annotation/AnnotationsList.java b/dx/src/com/android/dx/rop/annotation/AnnotationsList.java deleted file mode 100644 index 43a07ba94..000000000 --- a/dx/src/com/android/dx/rop/annotation/AnnotationsList.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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.annotation; - -import com.android.dx.util.FixedSizeList; - -/** - * List of {@link Annotations} instances. - */ -public final class AnnotationsList - extends FixedSizeList { - /** non-null; immutable empty instance */ - public static final AnnotationsList EMPTY = new AnnotationsList(0); - - /** - * Constructs an immutable instance which is the combination of - * the two given instances. The two instances must each have the - * same number of elements, and each pair of elements must contain - * disjoint sets of types. - * - * @param list1 non-null; an instance - * @param list2 non-null; the other instance - * @return non-null; the combination - */ - public static AnnotationsList combine(AnnotationsList list1, - AnnotationsList list2) { - int size = list1.size(); - - if (size != list2.size()) { - throw new IllegalArgumentException("list1.size() != list2.size()"); - } - - AnnotationsList result = new AnnotationsList(size); - - for (int i = 0; i < size; i++) { - Annotations a1 = list1.get(i); - Annotations a2 = list2.get(i); - result.set(i, Annotations.combine(a1, a2)); - } - - result.setImmutable(); - return result; - } - - /** - * Constructs an instance. All indices initially contain <code>null</code>. - * - * @param size the size of the list - */ - public AnnotationsList(int size) { - super(size); - } - - /** - * Gets the element at the given index. 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</code>. - * - * @param n >= 0, < size(); which index - * @return non-null; element at that index - */ - public Annotations get(int n) { - return (Annotations) get0(n); - } - - /** - * Sets the element at the given index. The given element must be - * immutable. - * - * @param n >= 0, < size(); which index - * @param a null-ok; the element to set at <code>n</code> - */ - public void set(int n, Annotations a) { - a.throwIfMutable(); - set0(n, a); - } -} diff --git a/dx/src/com/android/dx/rop/annotation/NameValuePair.java b/dx/src/com/android/dx/rop/annotation/NameValuePair.java deleted file mode 100644 index dadabaa71..000000000 --- a/dx/src/com/android/dx/rop/annotation/NameValuePair.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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.annotation; - -import com.android.dx.rop.cst.Constant; -import com.android.dx.rop.cst.CstString; -import com.android.dx.rop.cst.CstUtf8; - -/** - * A (name, value) pair. These are used as the contents of an annotation. - */ -public final class NameValuePair implements Comparable<NameValuePair> { - /** non-null; the name */ - private final CstUtf8 name; - - /** non-null; the value */ - private final Constant value; - - /** - * Construct an instance. - * - * @param name non-null; the name - * @param value non-null; the value - */ - public NameValuePair(CstUtf8 name, Constant value) { - if (name == null) { - throw new NullPointerException("name == null"); - } - - if (value == null) { - throw new NullPointerException("value == null"); - } - - // Reject CstUtf8 values. (They should be CstStrings.) - if (value instanceof CstUtf8) { - throw new IllegalArgumentException("bad value: " + value); - } - - this.name = name; - this.value = value; - } - - /** {@inheritDoc} */ - public String toString() { - return name.toHuman() + ":" + value; - } - - /** {@inheritDoc} */ - public int hashCode() { - return name.hashCode() * 31 + value.hashCode(); - } - - /** {@inheritDoc} */ - public boolean equals(Object other) { - if (! (other instanceof NameValuePair)) { - return false; - } - - NameValuePair otherPair = (NameValuePair) other; - - return name.equals(otherPair.name) - && value.equals(otherPair.value); - } - - /** - * {@inheritDoc} - * - * <p>Instances of this class compare in name-major and value-minor - * order.</p> - */ - public int compareTo(NameValuePair other) { - int result = name.compareTo(other.name); - - if (result != 0) { - return result; - } - - return value.compareTo(other.value); - } - - /** - * Gets the name. - * - * @return non-null; the name - */ - public CstUtf8 getName() { - return name; - } - - /** - * Gets the value. - * - * @return non-null; the valute - */ - public Constant getValue() { - return value; - } -} diff --git a/dx/src/com/android/dx/rop/code/AccessFlags.java b/dx/src/com/android/dx/rop/code/AccessFlags.java deleted file mode 100644 index 265cfa619..000000000 --- a/dx/src/com/android/dx/rop/code/AccessFlags.java +++ /dev/null @@ -1,374 +0,0 @@ -/* - * 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.util.Hex; - -/** - * Constants used as "access flags" in various places in classes, and - * related utilities. Although, at the rop layer, flags are generally - * ignored, this is the layer of communication, and as such, this - * package is where these definitions belong. The flag definitions are - * identical to Java access flags, but <code>ACC_SUPER</code> isn't - * used at all in translated code, and <code>ACC_SYNCHRONIZED</code> - * is only used in a very limited way. - */ -public final class AccessFlags { - /** public member / class */ - public static final int ACC_PUBLIC = 0x0001; - - /** private member */ - public static final int ACC_PRIVATE = 0x0002; - - /** protected member */ - public static final int ACC_PROTECTED = 0x0004; - - /** static member */ - public static final int ACC_STATIC = 0x0008; - - /** final member / class */ - public static final int ACC_FINAL = 0x0010; - - /** - * synchronized method; only valid in dex files for <code>native</code> - * methods - */ - public static final int ACC_SYNCHRONIZED = 0x0020; - - /** - * class with new-style <code>invokespecial</code> for superclass - * method access - */ - public static final int ACC_SUPER = 0x0020; - - /** volatile field */ - public static final int ACC_VOLATILE = 0x0040; - - /** bridge method (generated) */ - public static final int ACC_BRIDGE = 0x0040; - - /** transient field */ - public static final int ACC_TRANSIENT = 0x0080; - - /** varargs method */ - public static final int ACC_VARARGS = 0x0080; - - /** native method */ - public static final int ACC_NATIVE = 0x0100; - - /** "class" is in fact an public static final interface */ - public static final int ACC_INTERFACE = 0x0200; - - /** abstract method / class */ - public static final int ACC_ABSTRACT = 0x0400; - - /** - * method with strict floating point (<code>strictfp</code>) - * behavior - */ - public static final int ACC_STRICT = 0x0800; - - /** synthetic member */ - public static final int ACC_SYNTHETIC = 0x1000; - - /** class is an annotation type */ - public static final int ACC_ANNOTATION = 0x2000; - - /** - * class is an enumerated type; field is an element of an enumerated - * type - */ - public static final int ACC_ENUM = 0x4000; - - /** method is a constructor */ - public static final int ACC_CONSTRUCTOR = 0x10000; - - /** - * method was declared <code>synchronized</code>; has no effect on - * execution (other than inspecting this flag, per se) - */ - public static final int ACC_DECLARED_SYNCHRONIZED = 0x20000; - - /** flags defined on classes */ - public static final int CLASS_FLAGS = - ACC_PUBLIC | ACC_FINAL | ACC_SUPER | ACC_INTERFACE | ACC_ABSTRACT | - ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM; - - /** flags defined on inner classes */ - public static final int INNER_CLASS_FLAGS = - ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL | - ACC_INTERFACE | ACC_ABSTRACT | ACC_SYNTHETIC | ACC_ANNOTATION | - ACC_ENUM; - - /** flags defined on fields */ - public static final int FIELD_FLAGS = - ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL | - ACC_VOLATILE | ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM; - - /** flags defined on methods */ - public static final int METHOD_FLAGS = - ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL | - ACC_SYNCHRONIZED | ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE | - ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC | ACC_CONSTRUCTOR | - ACC_DECLARED_SYNCHRONIZED; - - /** indicates conversion of class flags */ - private static final int CONV_CLASS = 1; - - /** indicates conversion of field flags */ - private static final int CONV_FIELD = 2; - - /** indicates conversion of method flags */ - private static final int CONV_METHOD = 3; - - /** - * This class is uninstantiable. - */ - private AccessFlags() { - // This space intentionally left blank. - } - - /** - * Returns a human-oriented string representing the given access flags, - * as defined on classes (not fields or methods). - * - * @param flags the flags - * @return non-null; human-oriented string - */ - public static String classString(int flags) { - return humanHelper(flags, CLASS_FLAGS, CONV_CLASS); - } - - /** - * Returns a human-oriented string representing the given access flags, - * as defined on inner classes. - * - * @param flags the flags - * @return non-null; human-oriented string - */ - public static String innerClassString(int flags) { - return humanHelper(flags, INNER_CLASS_FLAGS, CONV_CLASS); - } - - /** - * Returns a human-oriented string representing the given access flags, - * as defined on fields (not classes or methods). - * - * @param flags the flags - * @return non-null; human-oriented string - */ - public static String fieldString(int flags) { - return humanHelper(flags, FIELD_FLAGS, CONV_FIELD); - } - - /** - * Returns a human-oriented string representing the given access flags, - * as defined on methods (not classes or fields). - * - * @param flags the flags - * @return non-null; human-oriented string - */ - public static String methodString(int flags) { - return humanHelper(flags, METHOD_FLAGS, CONV_METHOD); - } - - /** - * Returns whether the flag <code>ACC_PUBLIC</code> is on in the given - * flags. - * - * @param flags the flags to check - * @return the value of the <code>ACC_PUBLIC</code> flag - */ - public static boolean isPublic(int flags) { - return (flags & ACC_PUBLIC) != 0; - } - - /** - * Returns whether the flag <code>ACC_PROTECTED</code> is on in the given - * flags. - * - * @param flags the flags to check - * @return the value of the <code>ACC_PROTECTED</code> flag - */ - public static boolean isProtected(int flags) { - return (flags & ACC_PROTECTED) != 0; - } - - /** - * Returns whether the flag <code>ACC_PRIVATE</code> is on in the given - * flags. - * - * @param flags the flags to check - * @return the value of the <code>ACC_PRIVATE</code> flag - */ - public static boolean isPrivate(int flags) { - return (flags & ACC_PRIVATE) != 0; - } - - /** - * Returns whether the flag <code>ACC_STATIC</code> is on in the given - * flags. - * - * @param flags the flags to check - * @return the value of the <code>ACC_STATIC</code> flag - */ - public static boolean isStatic(int flags) { - return (flags & ACC_STATIC) != 0; - } - - /** - * Returns whether the flag <code>ACC_SYNCHRONIZED</code> is on in - * the given flags. - * - * @param flags the flags to check - * @return the value of the <code>ACC_SYNCHRONIZED</code> flag - */ - public static boolean isSynchronized(int flags) { - return (flags & ACC_SYNCHRONIZED) != 0; - } - - /** - * Returns whether the flag <code>ACC_ABSTRACT</code> is on in the given - * flags. - * - * @param flags the flags to check - * @return the value of the <code>ACC_ABSTRACT</code> flag - */ - public static boolean isAbstract(int flags) { - return (flags & ACC_ABSTRACT) != 0; - } - - /** - * Returns whether the flag <code>ACC_NATIVE</code> is on in the given - * flags. - * - * @param flags the flags to check - * @return the value of the <code>ACC_NATIVE</code> flag - */ - public static boolean isNative(int flags) { - return (flags & ACC_NATIVE) != 0; - } - - /** - * Returns whether the flag <code>ACC_ANNOTATION</code> is on in the given - * flags. - * - * @param flags the flags to check - * @return the value of the <code>ACC_ANNOTATION</code> flag - */ - public static boolean isAnnotation(int flags) { - return (flags & ACC_ANNOTATION) != 0; - } - - /** - * Returns whether the flag <code>ACC_DECLARED_SYNCHRONIZED</code> is - * on in the given flags. - * - * @param flags the flags to check - * @return the value of the <code>ACC_DECLARED_SYNCHRONIZED</code> flag - */ - public static boolean isDeclaredSynchronized(int flags) { - return (flags & ACC_DECLARED_SYNCHRONIZED) != 0; - } - - /** - * Helper to return a human-oriented string representing the given - * access flags. - * - * @param flags the defined flags - * @param mask mask for the "defined" bits - * @param what what the flags represent (one of <code>CONV_*</code>) - * @return non-null; human-oriented string - */ - private static String humanHelper(int flags, int mask, int what) { - StringBuffer sb = new StringBuffer(80); - int extra = flags & ~mask; - - flags &= mask; - - if ((flags & ACC_PUBLIC) != 0) { - sb.append("|public"); - } - if ((flags & ACC_PRIVATE) != 0) { - sb.append("|private"); - } - if ((flags & ACC_PROTECTED) != 0) { - sb.append("|protected"); - } - if ((flags & ACC_STATIC) != 0) { - sb.append("|static"); - } - if ((flags & ACC_FINAL) != 0) { - sb.append("|final"); - } - if ((flags & ACC_SYNCHRONIZED) != 0) { - if (what == CONV_CLASS) { - sb.append("|super"); - } else { - sb.append("|synchronized"); - } - } - if ((flags & ACC_VOLATILE) != 0) { - if (what == CONV_METHOD) { - sb.append("|bridge"); - } else { - sb.append("|volatile"); - } - } - if ((flags & ACC_TRANSIENT) != 0) { - if (what == CONV_METHOD) { - sb.append("|varargs"); - } else { - sb.append("|transient"); - } - } - if ((flags & ACC_NATIVE) != 0) { - sb.append("|native"); - } - if ((flags & ACC_INTERFACE) != 0) { - sb.append("|interface"); - } - if ((flags & ACC_ABSTRACT) != 0) { - sb.append("|abstract"); - } - if ((flags & ACC_STRICT) != 0) { - sb.append("|strictfp"); - } - if ((flags & ACC_SYNTHETIC) != 0) { - sb.append("|synthetic"); - } - if ((flags & ACC_ANNOTATION) != 0) { - sb.append("|annotation"); - } - if ((flags & ACC_ENUM) != 0) { - sb.append("|enum"); - } - if ((flags & ACC_CONSTRUCTOR) != 0) { - sb.append("|constructor"); - } - if ((flags & ACC_DECLARED_SYNCHRONIZED) != 0) { - sb.append("|declared_synchronized"); - } - - if ((extra != 0) || (sb.length() == 0)) { - sb.append('|'); - sb.append(Hex.u2(extra)); - } - - return sb.substring(1); - } -} diff --git a/dx/src/com/android/dx/rop/code/BasicBlock.java b/dx/src/com/android/dx/rop/code/BasicBlock.java deleted file mode 100644 index 66db5aa29..000000000 --- a/dx/src/com/android/dx/rop/code/BasicBlock.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * 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.TypeList; -import com.android.dx.util.Hex; -import com.android.dx.util.IntList; -import com.android.dx.util.LabeledItem; - -/** - * Basic block of register-based instructions. - */ -public final class BasicBlock implements LabeledItem { - /** >= 0; target label for this block */ - private final int label; - - /** non-null; list of instructions in this block */ - private final InsnList insns; - - /** - * non-null; full list of successors that this block may - * branch to - */ - private final IntList successors; - - /** - * >= -1; the primary / standard-flow / "default" successor, or - * <code>-1</code> if this block has no successors (that is, it - * exits the function/method) - */ - private final int primarySuccessor; - - /** - * Constructs an instance. The predecessor set is set to <code>null</code>. - * - * @param label >= 0; target label for this block - * @param insns non-null; list of instructions in this block - * @param successors non-null; full list of successors that this - * block may branch to - * @param primarySuccessor >= -1; the primary / standard-flow / - * "default" successor, or <code>-1</code> if this block has no - * successors (that is, it exits the function/method or is an - * unconditional throw) - */ - public BasicBlock(int label, InsnList insns, IntList successors, - int primarySuccessor) { - if (label < 0) { - throw new IllegalArgumentException("label < 0"); - } - - try { - insns.throwIfMutable(); - } catch (NullPointerException ex) { - // Elucidate exception. - throw new NullPointerException("insns == null"); - } - - int sz = insns.size(); - - if (sz == 0) { - throw new IllegalArgumentException("insns.size() == 0"); - } - - for (int i = sz - 2; i >= 0; i--) { - Rop one = insns.get(i).getOpcode(); - if (one.getBranchingness() != Rop.BRANCH_NONE) { - throw new IllegalArgumentException("insns[" + i + "] is a " + - "branch or can throw"); - } - } - - Insn lastInsn = insns.get(sz - 1); - if (lastInsn.getOpcode().getBranchingness() == Rop.BRANCH_NONE) { - throw new IllegalArgumentException("insns does not end with " + - "a branch or throwing " + - "instruction"); - } - - try { - successors.throwIfMutable(); - } catch (NullPointerException ex) { - // Elucidate exception. - throw new NullPointerException("successors == null"); - } - - if (primarySuccessor < -1) { - throw new IllegalArgumentException("primarySuccessor < -1"); - } - - if (primarySuccessor >= 0 && !successors.contains(primarySuccessor)) { - throw new IllegalArgumentException( - "primarySuccessor not in successors"); - } - - this.label = label; - this.insns = insns; - this.successors = successors; - this.primarySuccessor = primarySuccessor; - } - - /** - * {@inheritDoc} - * - * Instances of this class compare by identity. That is, - * <code>x.equals(y)</code> is only true if <code>x == y</code>. - */ - @Override - public boolean equals(Object other) { - return (this == other); - } - - /** - * {@inheritDoc} - * - * Return the identity hashcode of this instance. This is proper, - * since instances of this class compare by identity (see {@link #equals}). - */ - @Override - public int hashCode() { - return System.identityHashCode(this); - } - - /** - * Gets the target label of this block. - * - * @return >= 0; the label - */ - public int getLabel() { - return label; - } - - /** - * Gets the list of instructions inside this block. - * - * @return non-null; the instruction list - */ - public InsnList getInsns() { - return insns; - } - - /** - * Gets the list of successors that this block may branch to. - * - * @return non-null; the successors list - */ - public IntList getSuccessors() { - return successors; - } - - /** - * Gets the primary successor of this block. - * - * @return >= -1; the primary successor, or <code>-1</code> if this - * block has no successors at all - */ - public int getPrimarySuccessor() { - return primarySuccessor; - } - - /** - * Gets the secondary successor of this block. It is only valid to call - * this method on blocks that have exactly two successors. - * - * @return >= 0; the secondary successor - */ - public int getSecondarySuccessor() { - if (successors.size() != 2) { - throw new UnsupportedOperationException( - "block doesn't have exactly two successors"); - } - - int succ = successors.get(0); - if (succ == primarySuccessor) { - succ = successors.get(1); - } - - return succ; - } - - /** - * Gets the first instruction of this block. This is just a - * convenient shorthand for <code>getInsns().get(0)</code>. - * - * @return non-null; the first instruction - */ - public Insn getFirstInsn() { - return insns.get(0); - } - - /** - * Gets the last instruction of this block. This is just a - * convenient shorthand for <code>getInsns().getLast()</code>. - * - * @return non-null; the last instruction - */ - public Insn getLastInsn() { - return insns.getLast(); - } - - /** - * Returns whether this block might throw an exception. This is - * just a convenient shorthand for <code>getLastInsn().canThrow()</code>. - * - * @return <code>true</code> iff this block might throw an - * exception - */ - public boolean canThrow() { - return insns.getLast().canThrow(); - } - - /** - * Returns whether this block has any associated exception handlers. - * This is just a shorthand for inspecting the last instruction in - * the block to see if it could throw, and if so, whether it in fact - * has any associated handlers. - * - * @return <code>true</code> iff this block has any associated - * exception handlers - */ - public boolean hasExceptionHandlers() { - Insn lastInsn = insns.getLast(); - return lastInsn.getCatches().size() != 0; - } - - /** - * Returns the exception handler types associated with this block, - * if any. This is just a shorthand for inspecting the last - * instruction in the block to see if it could throw, and if so, - * grabbing the catch list out of it. If not, this returns an - * empty list (not <code>null</code>). - * - * @return non-null; the exception handler types associated with - * this block - */ - public TypeList getExceptionHandlerTypes() { - Insn lastInsn = insns.getLast(); - return lastInsn.getCatches(); - } - - /** - * Returns an instance that is identical to this one, except that - * the registers in each instruction are offset by the given - * amount. - * - * @param delta the amount to offset register numbers by - * @return non-null; an appropriately-constructed instance - */ - public BasicBlock withRegisterOffset(int delta) { - return new BasicBlock(label, insns.withRegisterOffset(delta), - successors, primarySuccessor); - } - - public String toString() { - return '{' + Hex.u2(label) + '}'; - } - - /** - * BasicBlock visitor interface - */ - public interface Visitor { - /** - * Visits a basic block - * @param b block visited - */ - public void visitBlock (BasicBlock b); - } -} diff --git a/dx/src/com/android/dx/rop/code/BasicBlockList.java b/dx/src/com/android/dx/rop/code/BasicBlockList.java deleted file mode 100644 index 6564318e1..000000000 --- a/dx/src/com/android/dx/rop/code/BasicBlockList.java +++ /dev/null @@ -1,398 +0,0 @@ -/* - * 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.StdTypeList; -import com.android.dx.rop.type.TypeList; -import com.android.dx.util.Hex; -import com.android.dx.util.IntList; -import com.android.dx.util.LabeledList; - -/** - * List of {@link BasicBlock} instances. - */ -public final class BasicBlockList extends LabeledList { - /** - * >= -1; the count of registers required by this method or - * <code>-1</code> if not yet calculated - */ - private int regCount; - - /** - * Constructs an instance. All indices initially contain <code>null</code>, - * and the first-block label is initially <code>-1</code>. - * - * @param size the size of the list - */ - public BasicBlockList(int size) { - super(size); - - regCount = -1; - } - - /** - * Constructs a mutable copy for <code>getMutableCopy()</code>. - * - * @param old block to copy - */ - private BasicBlockList (BasicBlockList old) { - super(old); - regCount = old.regCount; - } - - - /** - * Gets the element at the given index. 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</code>. - * - * @param n >= 0, < size(); which index - * @return non-null; element at that index - */ - public BasicBlock get(int n) { - return (BasicBlock) get0(n); - } - - /** - * Sets the basic block at the given index. - * - * @param n >= 0, < size(); which index - * @param bb null-ok; the element to set at <code>n</code> - */ - public void set(int n, BasicBlock bb) { - super.set(n, bb); - - // Reset regCount, since it will need to be recalculated. - regCount = -1; - } - - /** - * Returns how many registers this method requires. This is simply - * the maximum of register-number-plus-category referred to by this - * instance's instructions (indirectly through {@link BasicBlock} - * instances). - * - * @return >= 0; the register count - */ - public int getRegCount() { - if (regCount == -1) { - RegCountVisitor visitor = new RegCountVisitor(); - forEachInsn(visitor); - regCount = visitor.getRegCount(); - } - - return regCount; - } - - /** - * Gets the total instruction count for this instance. This is the - * sum of the instruction counts of each block. - * - * @return >= 0; the total instruction count - */ - public int getInstructionCount() { - int sz = size(); - int result = 0; - - for (int i = 0; i < sz; i++) { - BasicBlock one = (BasicBlock) getOrNull0(i); - if (one != null) { - result += one.getInsns().size(); - } - } - - return result; - } - - /** - * Gets the total instruction count for this instance, ignoring - * mark-local instructions which are not actually emitted. - * - * @return >= 0; the total instruction count - */ - public int getEffectiveInstructionCount() { - int sz = size(); - int result = 0; - - for (int i = 0; i < sz; i++) { - BasicBlock one = (BasicBlock) getOrNull0(i); - if (one != null) { - InsnList insns = one.getInsns(); - int insnsSz = insns.size(); - - for (int j = 0; j < insnsSz; j++) { - Insn insn = insns.get(j); - - if (insn.getOpcode().getOpcode() != RegOps.MARK_LOCAL) { - result++; - } - } - } - } - - return result; - } - - - /** - * Gets the first block in the list with the given label, if any. - * - * @param label >= 0; the label to look for - * @return non-null; the so-labelled block - * @throws IllegalArgumentException thrown if the label isn't found - */ - public BasicBlock labelToBlock(int label) { - int idx = indexOfLabel(label); - - if (idx < 0) { - throw new IllegalArgumentException("no such label: " - + Hex.u2(label)); - } - - return get(idx); - } - - /** - * Visits each instruction of each block in the list, in order. - * - * @param visitor non-null; visitor to use - */ - public void forEachInsn(Insn.Visitor visitor) { - int sz = size(); - - for (int i = 0; i < sz; i++) { - BasicBlock one = get(i); - InsnList insns = one.getInsns(); - insns.forEach(visitor); - } - } - - /** - * Returns an instance that is identical to this one, except that - * the registers in each instruction are offset by the given - * amount. Mutability of the result is inherited from the - * original. - * - * @param delta the amount to offset register numbers by - * @return non-null; an appropriately-constructed instance - */ - public BasicBlockList withRegisterOffset(int delta) { - int sz = size(); - BasicBlockList result = new BasicBlockList(sz); - - for (int i = 0; i < sz; i++) { - BasicBlock one = (BasicBlock) get0(i); - if (one != null) { - result.set(i, one.withRegisterOffset(delta)); - } - } - - if (isImmutable()) { - result.setImmutable(); - } - - return result; - } - - /** - * Returns a mutable copy of this list. - * - * @return non-null; an appropriately-constructed instance - */ - public BasicBlockList getMutableCopy() { - return new BasicBlockList(this); - } - - /** - * Gets the preferred successor for the given block. If the block - * only has one successor, then that is the preferred successor. - * Otherwise, if the block has a primay successor, then that is - * the preferred successor. If the block has no successors, then - * this returns <code>null</code>. - * - * @param block non-null; the block in question - * @return null-ok; the preferred successor, if any - */ - public BasicBlock preferredSuccessorOf(BasicBlock block) { - int primarySuccessor = block.getPrimarySuccessor(); - IntList successors = block.getSuccessors(); - int succSize = successors.size(); - - switch (succSize) { - case 0: { - return null; - } - case 1: { - return labelToBlock(successors.get(0)); - } - } - - if (primarySuccessor != -1) { - return labelToBlock(primarySuccessor); - } else { - return labelToBlock(successors.get(0)); - } - } - - /** - * Compares the catches of two blocks for equality. This includes - * both the catch types and target labels. - * - * @param block1 non-null; one block to compare - * @param block2 non-null; the other block to compare - * @return <code>true</code> if the two blocks' non-primary successors - * are identical - */ - public boolean catchesEqual(BasicBlock block1, - BasicBlock block2) { - TypeList catches1 = block1.getExceptionHandlerTypes(); - TypeList catches2 = block2.getExceptionHandlerTypes(); - - if (!StdTypeList.equalContents(catches1, catches2)) { - return false; - } - - IntList succ1 = block1.getSuccessors(); - IntList succ2 = block2.getSuccessors(); - int size = succ1.size(); // Both are guaranteed to be the same size. - - int primary1 = block1.getPrimarySuccessor(); - int primary2 = block2.getPrimarySuccessor(); - - if (((primary1 == -1) || (primary2 == -1)) - && (primary1 != primary2)) { - /* - * For the current purpose, both blocks in question must - * either both have a primary or both not have a primary to - * be considered equal, and it turns out here that that's not - * the case. - */ - return false; - } - - for (int i = 0; i < size; i++) { - int label1 = succ1.get(i); - int label2 = succ2.get(i); - - if (label1 == primary1) { - /* - * It should be the case that block2's primary is at the - * same index. If not, we consider the blocks unequal for - * the current purpose. - */ - if (label2 != primary2) { - return false; - } - continue; - } - - if (label1 != label2) { - return false; - } - } - - return true; - } - - /** - * Instruction visitor class for counting registers used. - */ - private static class RegCountVisitor - implements Insn.Visitor { - /** >= 0; register count in-progress */ - private int regCount; - - /** - * Constructs an instance. - */ - public RegCountVisitor() { - regCount = 0; - } - - /** - * Gets the register count. - * - * @return >= 0; the count - */ - public int getRegCount() { - return regCount; - } - - /** {@inheritDoc} */ - public void visitPlainInsn(PlainInsn insn) { - visit(insn); - } - - /** {@inheritDoc} */ - public void visitPlainCstInsn(PlainCstInsn insn) { - visit(insn); - } - - /** {@inheritDoc} */ - public void visitSwitchInsn(SwitchInsn insn) { - visit(insn); - } - - /** {@inheritDoc} */ - public void visitThrowingCstInsn(ThrowingCstInsn insn) { - visit(insn); - } - - /** {@inheritDoc} */ - public void visitThrowingInsn(ThrowingInsn insn) { - visit(insn); - } - - /** {@inheritDoc} */ - public void visitFillArrayDataInsn(FillArrayDataInsn insn) { - visit(insn); - } - - /** - * Helper for all the <code>visit*</code> methods. - * - * @param insn non-null; instruction being visited - */ - private void visit(Insn insn) { - RegisterSpec result = insn.getResult(); - - if (result != null) { - processReg(result); - } - - RegisterSpecList sources = insn.getSources(); - int sz = sources.size(); - - for (int i = 0; i < sz; i++) { - processReg(sources.get(i)); - } - } - - /** - * Processes the given register spec. - * - * @param spec non-null; the register spec - */ - private void processReg(RegisterSpec spec) { - int reg = spec.getNextReg(); - - if (reg > regCount) { - regCount = reg; - } - } - } -} diff --git a/dx/src/com/android/dx/rop/code/ConservativeTranslationAdvice.java b/dx/src/com/android/dx/rop/code/ConservativeTranslationAdvice.java deleted file mode 100644 index a9da10932..000000000 --- a/dx/src/com/android/dx/rop/code/ConservativeTranslationAdvice.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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; - -/** - * Implementation of {@link TranslationAdvice} which conservatively answers - * <code>false</code> to all methods. - */ -public final class ConservativeTranslationAdvice - implements TranslationAdvice { - /** non-null; standard instance of this class */ - public static final ConservativeTranslationAdvice THE_ONE = - new ConservativeTranslationAdvice(); - - /** - * This class is not publicly instantiable. Use {@link #THE_ONE}. - */ - private ConservativeTranslationAdvice() { - // This space intentionally left blank. - } - - /** {@inheritDoc} */ - public boolean hasConstantOperation(Rop opcode, - RegisterSpec sourceA, RegisterSpec sourceB) { - return false; - } - - /** {@inheritDoc} */ - public boolean requiresSourcesInOrder(Rop opcode, - RegisterSpecList sources) { - return false; - } - - /** {@inheritDoc} */ - public int getMaxOptimalRegisterCount() { - return Integer.MAX_VALUE; - } -} diff --git a/dx/src/com/android/dx/rop/code/CstInsn.java b/dx/src/com/android/dx/rop/code/CstInsn.java deleted file mode 100644 index d1cf523a5..000000000 --- a/dx/src/com/android/dx/rop/code/CstInsn.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.cst.Constant; - -/** - * Instruction which contains an explicit reference to a constant. - */ -public abstract class CstInsn - extends Insn { - /** non-null; the constant */ - private final Constant cst; - - /** - * Constructs an instance. - * - * @param opcode non-null; the opcode - * @param position non-null; source position - * @param result null-ok; spec for the result, if any - * @param sources non-null; specs for all the sources - * @param cst non-null; constant - */ - public CstInsn(Rop opcode, SourcePosition position, RegisterSpec result, - RegisterSpecList sources, Constant cst) { - super(opcode, position, result, sources); - - if (cst == null) { - throw new NullPointerException("cst == null"); - } - - this.cst = cst; - } - - /** {@inheritDoc} */ - @Override - public String getInlineString() { - return cst.toHuman(); - } - - /** - * Gets the constant. - * - * @return non-null; the constant - */ - public Constant getConstant() { - return cst; - } - - /** {@inheritDoc} */ - @Override - public boolean contentEquals(Insn b) { - /* - * The cast (CstInsn)b below should always succeed since - * Insn.contentEquals compares classes of this and b. - */ - return super.contentEquals(b) - && cst.equals(((CstInsn)b).getConstant()); - } -} diff --git a/dx/src/com/android/dx/rop/code/DexTranslationAdvice.java b/dx/src/com/android/dx/rop/code/DexTranslationAdvice.java deleted file mode 100644 index 1c2382464..000000000 --- a/dx/src/com/android/dx/rop/code/DexTranslationAdvice.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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.cst.CstInteger; -import com.android.dx.rop.type.Type; - -/** - * Implementation of {@link TranslationAdvice} which represents what - * the dex format will be able to represent. - */ -public final class DexTranslationAdvice - implements TranslationAdvice { - /** non-null; standard instance of this class */ - public static final DexTranslationAdvice THE_ONE = - new DexTranslationAdvice(); - - /** debug advice for disabling invoke-range optimization */ - public static final DexTranslationAdvice NO_SOURCES_IN_ORDER = - new DexTranslationAdvice(true); - - /** - * The minimum source width, in register units, for an invoke - * instruction that requires its sources to be in order and contiguous. - */ - private static final int MIN_INVOKE_IN_ORDER = 6; - - /** when true: always returns false for requiresSourcesInOrder */ - private final boolean disableSourcesInOrder; - - /** - * This class is not publicly instantiable. Use {@link #THE_ONE}. - */ - private DexTranslationAdvice() { - disableSourcesInOrder = false; - } - - private DexTranslationAdvice(boolean disableInvokeRange) { - this.disableSourcesInOrder = disableInvokeRange; - } - - /** {@inheritDoc} */ - public boolean hasConstantOperation(Rop opcode, - RegisterSpec sourceA, RegisterSpec sourceB) { - if (sourceA.getType() != Type.INT) { - return false; - } - - if (! (sourceB.getTypeBearer() instanceof CstInteger)) { - return false; - } - - CstInteger cst = (CstInteger) sourceB.getTypeBearer(); - - // TODO handle rsub - switch (opcode.getOpcode()) { - // These have 8 and 16 bit cst representations - case RegOps.REM: - case RegOps.ADD: - case RegOps.MUL: - case RegOps.DIV: - case RegOps.AND: - case RegOps.OR: - case RegOps.XOR: - return cst.fitsIn16Bits(); - // These only have 8 bit cst reps - case RegOps.SHL: - case RegOps.SHR: - case RegOps.USHR: - return cst.fitsIn8Bits(); - default: - return false; - } - } - - /** {@inheritDoc} */ - public boolean requiresSourcesInOrder(Rop opcode, - RegisterSpecList sources) { - - return !disableSourcesInOrder && opcode.isCallLike() - && totalRopWidth(sources) >= MIN_INVOKE_IN_ORDER; - } - - /** - * Calculates the total rop width of the list of SSA registers - * - * @param sources non-null; list of SSA registers - * @return >= 0 rop-form width in register units - */ - private int totalRopWidth(RegisterSpecList sources) { - int sz = sources.size(); - int total = 0; - - for (int i = 0; i < sz; i++) { - total += sources.get(i).getCategory(); - } - - return total; - } - - /** {@inheritDoc} */ - public int getMaxOptimalRegisterCount() { - return 16; - } -} diff --git a/dx/src/com/android/dx/rop/code/Exceptions.java b/dx/src/com/android/dx/rop/code/Exceptions.java deleted file mode 100644 index 3ef4879e6..000000000 --- a/dx/src/com/android/dx/rop/code/Exceptions.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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.StdTypeList; -import com.android.dx.rop.type.Type; - -/** - * Common exception types. - */ -public final class Exceptions { - /** non-null; the type <code>java.lang.ArithmeticException</code> */ - public static final Type TYPE_ArithmeticException = - Type.intern("Ljava/lang/ArithmeticException;"); - - /** - * non-null; the type - * <code>java.lang.ArrayIndexOutOfBoundsException</code> - */ - public static final Type TYPE_ArrayIndexOutOfBoundsException = - Type.intern("Ljava/lang/ArrayIndexOutOfBoundsException;"); - - /** non-null; the type <code>java.lang.ArrayStoreException</code> */ - public static final Type TYPE_ArrayStoreException = - Type.intern("Ljava/lang/ArrayStoreException;"); - - /** non-null; the type <code>java.lang.ClassCastException</code> */ - public static final Type TYPE_ClassCastException = - Type.intern("Ljava/lang/ClassCastException;"); - - /** non-null; the type <code>java.lang.Error</code> */ - public static final Type TYPE_Error = Type.intern("Ljava/lang/Error;"); - - /** - * non-null; the type - * <code>java.lang.IllegalMonitorStateException</code> - */ - public static final Type TYPE_IllegalMonitorStateException = - Type.intern("Ljava/lang/IllegalMonitorStateException;"); - - /** non-null; the type <code>java.lang.NegativeArraySizeException</code> */ - public static final Type TYPE_NegativeArraySizeException = - Type.intern("Ljava/lang/NegativeArraySizeException;"); - - /** non-null; the type <code>java.lang.NullPointerException</code> */ - public static final Type TYPE_NullPointerException = - Type.intern("Ljava/lang/NullPointerException;"); - - /** non-null; the list <code>[java.lang.Error]</code> */ - public static final StdTypeList LIST_Error = StdTypeList.make(TYPE_Error); - - /** - * non-null; the list <code>[java.lang.Error, - * java.lang.ArithmeticException]</code> - */ - public static final StdTypeList LIST_Error_ArithmeticException = - StdTypeList.make(TYPE_Error, TYPE_ArithmeticException); - - /** - * non-null; the list <code>[java.lang.Error, - * java.lang.ClassCastException]</code> - */ - public static final StdTypeList LIST_Error_ClassCastException = - StdTypeList.make(TYPE_Error, TYPE_ClassCastException); - - /** - * non-null; the list <code>[java.lang.Error, - * java.lang.NegativeArraySizeException]</code> - */ - public static final StdTypeList LIST_Error_NegativeArraySizeException = - StdTypeList.make(TYPE_Error, TYPE_NegativeArraySizeException); - - /** - * non-null; the list <code>[java.lang.Error, - * java.lang.NullPointerException]</code> - */ - public static final StdTypeList LIST_Error_NullPointerException = - StdTypeList.make(TYPE_Error, TYPE_NullPointerException); - - /** - * non-null; the list <code>[java.lang.Error, - * java.lang.NullPointerException, - * java.lang.ArrayIndexOutOfBoundsException]</code> - */ - public static final StdTypeList LIST_Error_Null_ArrayIndexOutOfBounds = - StdTypeList.make(TYPE_Error, - TYPE_NullPointerException, - TYPE_ArrayIndexOutOfBoundsException); - - /** - * non-null; the list <code>[java.lang.Error, - * java.lang.NullPointerException, - * java.lang.ArrayIndexOutOfBoundsException, - * java.lang.ArrayStoreException]</code> - */ - public static final StdTypeList LIST_Error_Null_ArrayIndex_ArrayStore = - StdTypeList.make(TYPE_Error, - TYPE_NullPointerException, - TYPE_ArrayIndexOutOfBoundsException, - TYPE_ArrayStoreException); - - /** - * non-null; the list <code>[java.lang.Error, - * java.lang.NullPointerException, - * java.lang.IllegalMonitorStateException]</code> - */ - public static final StdTypeList - LIST_Error_Null_IllegalMonitorStateException = - StdTypeList.make(TYPE_Error, - TYPE_NullPointerException, - TYPE_IllegalMonitorStateException); - - /** - * This class is uninstantiable. - */ - private Exceptions() { - // This space intentionally left blank. - } -} diff --git a/dx/src/com/android/dx/rop/code/FillArrayDataInsn.java b/dx/src/com/android/dx/rop/code/FillArrayDataInsn.java deleted file mode 100644 index 3798afbf2..000000000 --- a/dx/src/com/android/dx/rop/code/FillArrayDataInsn.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2008 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.cst.Constant; -import com.android.dx.rop.type.Type; -import com.android.dx.rop.type.TypeList; -import com.android.dx.rop.type.StdTypeList; - -import java.util.ArrayList; - -/** - * Instruction which fills a newly created array with a predefined list of - * constant values. - */ -public final class FillArrayDataInsn - extends Insn { - - /** non-null: initial values to fill the newly created array */ - private final ArrayList<Constant> initValues; - - /** - * non-null: type of the array. Will be used to determine the width of - * elements in the array-data table. - */ - private final Constant arrayType; - - /** - * Constructs an instance. - * - * @param opcode non-null; the opcode - * @param position non-null; source position - * @param sources non-null; specs for all the sources - * @param initValues non-null; list of initial values to fill the array - * @param cst non-null; type of the new array - */ - public FillArrayDataInsn(Rop opcode, SourcePosition position, - RegisterSpecList sources, - ArrayList<Constant> initValues, - Constant cst) { - super(opcode, position, null, sources); - - if (opcode.getBranchingness() != Rop.BRANCH_NONE) { - throw new IllegalArgumentException("bogus branchingness"); - } - - this.initValues = initValues; - this.arrayType = cst; - } - - - /** {@inheritDoc} */ - @Override - public TypeList getCatches() { - return StdTypeList.EMPTY; - } - - /** - * Return the list of init values - * @return non-null; list of init values - */ - public ArrayList<Constant> getInitValues() { - return initValues; - } - - /** - * Return the type of the newly created array - * @return non-null; array type - */ - public Constant getConstant() { - return arrayType; - } - - /** {@inheritDoc} */ - @Override - public void accept(Visitor visitor) { - visitor.visitFillArrayDataInsn(this); - } - - /** {@inheritDoc} */ - @Override - public Insn withAddedCatch(Type type) { - throw new UnsupportedOperationException("unsupported"); - } - - /** {@inheritDoc} */ - @Override - public Insn withRegisterOffset(int delta) { - return new FillArrayDataInsn(getOpcode(), getPosition(), - getSources().withOffset(delta), - initValues, arrayType); - } - - /** {@inheritDoc} */ - @Override - public Insn withNewRegisters(RegisterSpec result, - RegisterSpecList sources) { - - return new FillArrayDataInsn(getOpcode(), getPosition(), - sources, initValues, arrayType); - } -} diff --git a/dx/src/com/android/dx/rop/code/Insn.java b/dx/src/com/android/dx/rop/code/Insn.java deleted file mode 100644 index b1ad0ade4..000000000 --- a/dx/src/com/android/dx/rop/code/Insn.java +++ /dev/null @@ -1,458 +0,0 @@ -/* - * 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.cst.CstUtf8; -import com.android.dx.rop.cst.Constant; -import com.android.dx.rop.type.StdTypeList; -import com.android.dx.rop.type.Type; -import com.android.dx.rop.type.TypeList; -import com.android.dx.util.ToHuman; - -/** - * A register-based instruction. An instruction is the combination of - * an opcode (which specifies operation and source/result types), a - * list of actual sources and result registers/values, and additional - * information. - */ -public abstract class Insn implements ToHuman { - /** non-null; opcode */ - private final Rop opcode; - - /** non-null; source position */ - private final SourcePosition position; - - /** null-ok; spec for the result of this instruction, if any */ - private final RegisterSpec result; - - /** non-null; specs for all the sources of this instruction */ - private final RegisterSpecList sources; - - /** - * Constructs an instance. - * - * @param opcode non-null; the opcode - * @param position non-null; source position - * @param result null-ok; spec for the result, if any - * @param sources non-null; specs for all the sources - */ - public Insn(Rop opcode, SourcePosition position, RegisterSpec result, - RegisterSpecList sources) { - if (opcode == null) { - throw new NullPointerException("opcode == null"); - } - - if (position == null) { - throw new NullPointerException("position == null"); - } - - if (sources == null) { - throw new NullPointerException("sources == null"); - } - - this.opcode = opcode; - this.position = position; - this.result = result; - this.sources = sources; - } - - /** - * {@inheritDoc} - * - * Instances of this class compare by identity. That is, - * <code>x.equals(y)</code> is only true if <code>x == y</code>. - */ - @Override - public final boolean equals(Object other) { - return (this == other); - } - - /** - * {@inheritDoc} - * - * This implementation returns the identity hashcode of this - * instance. This is proper, since instances of this class compare - * by identity (see {@link #equals}). - */ - @Override - public final int hashCode() { - return System.identityHashCode(this); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return toStringWithInline(getInlineString()); - } - - /** - * Gets a human-oriented (and slightly lossy) string for this instance. - * - * @return non-null; the human string form - */ - public String toHuman() { - return toHumanWithInline(getInlineString()); - } - - /** - * Gets an "inline" string portion for toHuman(), if available. This - * is the portion that appears after the Rop opcode - * - * @return null-ok; if non-null, the inline text for toHuman() - */ - public String getInlineString() { - return null; - } - - /** - * Gets the opcode. - * - * @return non-null; the opcode - */ - public final Rop getOpcode() { - return opcode; - } - - /** - * Gets the source position. - * - * @return non-null; the source position - */ - public final SourcePosition getPosition() { - return position; - } - - /** - * Gets the result spec, if any. A return value of <code>null</code> - * means this instruction returns nothing. - * - * @return null-ok; the result spec, if any - */ - public final RegisterSpec getResult() { - return result; - } - - /** - * Gets the spec of a local variable assignment that occurs at this - * instruction, or null if no local variable assignment occurs. This - * may be the result register, or for <code>mark-local</code> insns - * it may be the source. - * - * @return null-ok; a named register spec or null - */ - public final RegisterSpec getLocalAssignment() { - RegisterSpec assignment; - if (opcode.getOpcode() == RegOps.MARK_LOCAL) { - assignment = sources.get(0); - } else { - assignment = result; - } - - if (assignment == null) { - return null; - } - - LocalItem localItem = assignment.getLocalItem(); - - if (localItem == null) { - return null; - } - - return assignment; - } - - /** - * Gets the source specs. - * - * @return non-null; the source specs - */ - public final RegisterSpecList getSources() { - return sources; - } - - /** - * Gets whether this instruction can possibly throw an exception. This - * is just a convenient wrapper for <code>getOpcode().canThrow()</code>. - * - * @return <code>true</code> iff this instruction can possibly throw - */ - public final boolean canThrow() { - return opcode.canThrow(); - } - - /** - * Gets the list of possibly-caught exceptions. This returns {@link - * StdTypeList#EMPTY} if this instruction has no handlers, - * which can be <i>either</i> if this instruction can't possibly - * throw or if it merely doesn't handle any of its possible - * exceptions. To determine whether this instruction can throw, - * use {@link #canThrow}. - * - * @return non-null; the catches list - */ - public abstract TypeList getCatches(); - - /** - * Calls the appropriate method on the given visitor, depending on the - * class of this instance. Subclasses must override this. - * - * @param visitor non-null; the visitor to call on - */ - public abstract void accept(Visitor visitor); - - /** - * Returns an instance that is just like this one, except that it - * has a catch list with the given item appended to the end. This - * method throws an exception if this instance can't possibly - * throw. To determine whether this instruction can throw, use - * {@link #canThrow}. - * - * @param type non-null; type to append to the catch list - * @return non-null; an appropriately-constructed instance - */ - public abstract Insn withAddedCatch(Type type); - - /** - * Returns an instance that is just like this one, except that all - * register references have been offset by the given delta. - * - * @param delta the amount to offset register references by - * @return non-null; an appropriately-constructed instance - */ - public abstract Insn withRegisterOffset(int delta); - - /** - * Returns an instance that is just like this one, except that, if - * possible, the insn is converted into a version in which the last - * source (if it is a constant) is represented directly rather than - * as a register reference. <code>this</code> is returned in cases where - * the translation is not possible. - * - * @return non-null; an appropriately-constructed instance - */ - public Insn withLastSourceLiteral() { - return this; - } - - /** - * Returns an exact copy of this Insn - * - * @return non-null; an appropriately-constructed instance - */ - public Insn copy() { - return withRegisterOffset(0); - } - - - /** - * Compares, handling nulls safely - * - * @param a first object - * @param b second object - * @return true if they're equal or both null. - */ - private static boolean equalsHandleNulls (Object a, Object b) { - return (a == b) || ((a != null) && a.equals(b)); - } - - /** - * Compares Insn contents, since <code>Insn.equals()</code> is defined - * to be an identity compare. Insn's are <code>contentEquals()</code> - * if they have the same opcode, registers, source position, and other - * metadata. - * - * @return true in the case described above - */ - public boolean contentEquals(Insn b) { - return opcode == b.getOpcode() - && position.equals(b.getPosition()) - && (getClass() == b.getClass()) - && equalsHandleNulls(result, b.getResult()) - && equalsHandleNulls(sources, b.getSources()) - && StdTypeList.equalContents(getCatches(), b.getCatches()); - } - - /** - * Returns an instance that is just like this one, except - * with new result and source registers. - * - * @param result null-ok; new result register - * @param sources non-null; new sources registers - * @return non-null; an appropriately-constructed instance - */ - public abstract Insn withNewRegisters(RegisterSpec result, - RegisterSpecList sources); - - /** - * Returns the string form of this instance, with the given bit added in - * the standard location for an inline argument. - * - * @param extra null-ok; the inline argument string - * @return non-null; the string form - */ - protected final String toStringWithInline(String extra) { - StringBuffer sb = new StringBuffer(80); - - sb.append("Insn{"); - sb.append(position); - sb.append(' '); - sb.append(opcode); - - if (extra != null) { - sb.append(' '); - sb.append(extra); - } - - sb.append(" :: "); - - if (result != null) { - sb.append(result); - sb.append(" <- "); - } - - sb.append(sources); - sb.append('}'); - - return sb.toString(); - } - - /** - * Returns the human string form of this instance, with the given - * bit added in the standard location for an inline argument. - * - * @param extra null-ok; the inline argument string - * @return non-null; the human string form - */ - protected final String toHumanWithInline(String extra) { - StringBuffer sb = new StringBuffer(80); - - sb.append(position); - sb.append(": "); - sb.append(opcode.getNickname()); - - if (extra != null) { - sb.append("("); - sb.append(extra); - sb.append(")"); - } - - if (result == null) { - sb.append(" ."); - } else { - sb.append(" "); - sb.append(result.toHuman()); - } - - sb.append(" <-"); - - int sz = sources.size(); - if (sz == 0) { - sb.append(" ."); - } else { - for (int i = 0; i < sz; i++) { - sb.append(" "); - sb.append(sources.get(i).toHuman()); - } - } - - return sb.toString(); - } - - - /** - * Visitor interface for this (outer) class. - */ - public static interface Visitor { - /** - * Visits a {@link PlainInsn}. - * - * @param insn non-null; the instruction to visit - */ - public void visitPlainInsn(PlainInsn insn); - - /** - * Visits a {@link PlainCstInsn}. - * - * @param insn non-null; the instruction to visit - */ - public void visitPlainCstInsn(PlainCstInsn insn); - - /** - * Visits a {@link SwitchInsn}. - * - * @param insn non-null; the instruction to visit - */ - public void visitSwitchInsn(SwitchInsn insn); - - /** - * Visits a {@link ThrowingCstInsn}. - * - * @param insn non-null; the instruction to visit - */ - public void visitThrowingCstInsn(ThrowingCstInsn insn); - - /** - * Visits a {@link ThrowingInsn}. - * - * @param insn non-null; the instruction to visit - */ - public void visitThrowingInsn(ThrowingInsn insn); - - /** - * Visits a {@link FillArrayDataInsn}. - * - * @param insn non-null; the instruction to visit - */ - public void visitFillArrayDataInsn(FillArrayDataInsn insn); - } - - /** - * Base implementation of {@link Visitor}, which has empty method - * bodies for all methods. - */ - public static class BaseVisitor implements Visitor { - /** {@inheritDoc} */ - public void visitPlainInsn(PlainInsn insn) { - // This space intentionally left blank. - } - - /** {@inheritDoc} */ - public void visitPlainCstInsn(PlainCstInsn insn) { - // This space intentionally left blank. - } - - /** {@inheritDoc} */ - public void visitSwitchInsn(SwitchInsn insn) { - // This space intentionally left blank. - } - - /** {@inheritDoc} */ - public void visitThrowingCstInsn(ThrowingCstInsn insn) { - // This space intentionally left blank. - } - - /** {@inheritDoc} */ - public void visitThrowingInsn(ThrowingInsn insn) { - // This space intentionally left blank. - } - - /** {@inheritDoc} */ - public void visitFillArrayDataInsn(FillArrayDataInsn insn) { - // This space intentionally left blank. - } - } -} diff --git a/dx/src/com/android/dx/rop/code/InsnList.java b/dx/src/com/android/dx/rop/code/InsnList.java deleted file mode 100644 index 34f124cca..000000000 --- a/dx/src/com/android/dx/rop/code/InsnList.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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.util.FixedSizeList; - -/** - * List of {@link Insn} instances. - */ -public final class InsnList - extends FixedSizeList { - /** - * Constructs an instance. All indices initially contain <code>null</code>. - * - * @param size the size of the list - */ - public InsnList(int size) { - super(size); - } - - /** - * Gets the element at the given index. 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</code>. - * - * @param n >= 0, < size(); which index - * @return non-null; element at that index - */ - public Insn get(int n) { - return (Insn) get0(n); - } - - /** - * Sets the instruction at the given index. - * - * @param n >= 0, < size(); which index - * @param insn non-null; the instruction to set at <code>n</code> - */ - public void set(int n, Insn insn) { - set0(n, insn); - } - - /** - * Gets the last instruction. This is just a convenient shorthand for - * <code>get(size() - 1)</code>. - * - * @return non-null; the last instruction - */ - public Insn getLast() { - return get(size() - 1); - } - - /** - * Visits each instruction in the list, in order. - * - * @param visitor non-null; visitor to use - */ - public void forEach(Insn.Visitor visitor) { - int sz = size(); - - for (int i = 0; i < sz; i++) { - get(i).accept(visitor); - } - } - - /** - * Compares the contents of this <code>InsnList</code> with another. - * The blocks must have the same number of insns, and each Insn must - * also return true to <code>Insn.contentEquals()</code>. - * - * @param b to compare - * @return true in the case described above. - */ - public boolean contentEquals(InsnList b) { - if (b == null) return false; - - int sz = size(); - - if (sz != b.size()) return false; - - for (int i = 0; i < sz; i++) { - if (!get(i).contentEquals(b.get(i))) { - return false; - } - } - - return true; - } - - /** - * Returns an instance that is identical to this one, except that - * the registers in each instruction are offset by the given - * amount. Mutability of the result is inherited from the - * original. - * - * @param delta the amount to offset register numbers by - * @return non-null; an appropriately-constructed instance - */ - public InsnList withRegisterOffset(int delta) { - int sz = size(); - InsnList result = new InsnList(sz); - - for (int i = 0; i < sz; i++) { - Insn one = (Insn) get0(i); - if (one != null) { - result.set0(i, one.withRegisterOffset(delta)); - } - } - - if (isImmutable()) { - result.setImmutable(); - } - - return result; - } -} diff --git a/dx/src/com/android/dx/rop/code/LocalItem.java b/dx/src/com/android/dx/rop/code/LocalItem.java deleted file mode 100644 index b1e1a4be6..000000000 --- a/dx/src/com/android/dx/rop/code/LocalItem.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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.cst.CstUtf8; - -/** - * A local variable item: either a name or a signature or both. - */ -public class LocalItem implements Comparable<LocalItem> { - - /** null-ok; local variable name */ - private final CstUtf8 name; - - /** null-ok; local variable signature */ - private final CstUtf8 signature; - - /** - * Make a new item. If both name and signature are null, null is returned. - * - * TODO: intern these - * - * @param name null-ok; local variable name - * @param signature null-ok; local variable signature - * @return non-null; appropriate instance. - */ - public static LocalItem make (CstUtf8 name, CstUtf8 signature) { - if (name == null && signature == null) { - return null; - } - - return new LocalItem (name, signature); - } - - /** - * Constructs instance. - * - * @param name null-ok; local variable name - * @param signature null-ok; local variable signature - */ - private LocalItem (CstUtf8 name, CstUtf8 signature) { - this.name = name; - this.signature = signature; - } - - /** {@inheritDoc} */ - @Override - public boolean equals (Object other) { - if (!(other instanceof LocalItem)) { - return false; - } - - LocalItem local = (LocalItem) other; - - return 0 == compareTo(local); - } - - /** - * Compares two strings like String.compareTo(), excepts treats a null - * as the least-possible string value. - * - * @return negative integer, zero, or positive integer in accordance - * with Comparable.compareTo() - */ - private static int compareHandlesNulls(CstUtf8 a, CstUtf8 b) { - if (a == b) { - return 0; - } else if (a == null) { - return -1; - } else if (b == null) { - return 1; - } else { - return a.compareTo(b); - } - } - - /** {@inheritDoc} */ - public int compareTo (LocalItem local) { - int ret; - - ret = compareHandlesNulls(name, local.name); - - if (ret != 0) { - return ret; - } - - ret = compareHandlesNulls(signature, local.signature); - - return ret; - } - - - /** {@inheritDoc} */ - @Override - public int hashCode () { - return (name == null ? 0 : name.hashCode()) * 31 - + (signature == null ? 0 : signature.hashCode()); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - if (name != null && signature == null) { - return name.toQuoted(); - } else if (name == null && signature == null) { - return ""; - } - - return "[" + (name == null ? "" : name.toQuoted()) - + "|" + (signature == null ? "" : signature.toQuoted()); - } - - /** - * Gets name. - * - * @return null-ok; name - */ - public CstUtf8 getName() { - return name; - } - - /** - * Gets signature. - * - * @return null-ok; signature - */ - public CstUtf8 getSignature() { - return signature; - } -} diff --git a/dx/src/com/android/dx/rop/code/LocalVariableExtractor.java b/dx/src/com/android/dx/rop/code/LocalVariableExtractor.java deleted file mode 100644 index 2d4cbced8..000000000 --- a/dx/src/com/android/dx/rop/code/LocalVariableExtractor.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * 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.util.Bits; -import com.android.dx.util.IntList; - -/** - * Code to figure out which local variables are active at which points in - * a method. - */ -public final class LocalVariableExtractor { - /** non-null; method being extracted from */ - private final RopMethod method; - - /** non-null; block list for the method */ - private final BasicBlockList blocks; - - /** non-null; result in-progress */ - private final LocalVariableInfo resultInfo; - - /** non-null; work set indicating blocks needing to be processed */ - private final int[] workSet; - - /** - * Extracts out all the local variable information from the given method. - * - * @param method non-null; the method to extract from - * @return non-null; the extracted information - */ - public static LocalVariableInfo extract(RopMethod method) { - LocalVariableExtractor lve = new LocalVariableExtractor(method); - return lve.doit(); - } - - /** - * Constructs an instance. This method is private. Use {@link #extract}. - * - * @param method non-null; the method to extract from - */ - private LocalVariableExtractor(RopMethod method) { - if (method == null) { - throw new NullPointerException("method == null"); - } - - BasicBlockList blocks = method.getBlocks(); - int maxLabel = blocks.getMaxLabel(); - - this.method = method; - this.blocks = blocks; - this.resultInfo = new LocalVariableInfo(method); - this.workSet = Bits.makeBitSet(maxLabel); - } - - /** - * Does the extraction. - * - * @return non-null; the extracted information - */ - private LocalVariableInfo doit() { - for (int label = method.getFirstLabel(); - label >= 0; - label = Bits.findFirst(workSet, 0)) { - Bits.clear(workSet, label); - processBlock(label); - } - - resultInfo.setImmutable(); - return resultInfo; - } - - /** - * Processes a single block. - * - * @param label >= 0; label of the block to process - */ - private void processBlock(int label) { - RegisterSpecSet primaryState = resultInfo.mutableCopyOfStarts(label); - BasicBlock block = blocks.labelToBlock(label); - InsnList insns = block.getInsns(); - int insnSz = insns.size(); - - /* - * We may have to treat the last instruction specially: If it - * can (but doesn't always) throw, and the exception can be - * caught within the same method, then we need to use the - * state *before* executing it to be what is merged into - * exception targets. - */ - Insn lastInsn = insns.getLast(); - boolean canThrowDuringLastInsn = block.hasExceptionHandlers() && - (insns.getLast().getResult() != null); - int freezeSecondaryStateAt = insnSz - 1; - RegisterSpecSet secondaryState = primaryState; - - /* - * Iterate over the instructions, adding information for each place - * that the active variable set changes. - */ - - for (int i = 0; i < insnSz; i++) { - if (canThrowDuringLastInsn && (i == freezeSecondaryStateAt)) { - // Until this point, primaryState == secondaryState. - primaryState.setImmutable(); - primaryState = primaryState.mutableCopy(); - } - - Insn insn = insns.get(i); - RegisterSpec result; - - result = insn.getLocalAssignment(); - - if (result == null) { - /* - * If an assignment assigns over an existing local, make - * sure to mark the local as going out of scope. - */ - - result = insn.getResult(); - - if (result != null - && primaryState.get(result.getReg()) != null) { - primaryState.remove(primaryState.get(result.getReg())); - } - continue; - } - - result = result.withSimpleType(); - - RegisterSpec already = primaryState.get(result); - /* - * The equals() check ensures we only add new info if - * the instruction causes a change to the set of - * active variables. - */ - if (!result.equals(already)) { - /* - * If this insn represents a local moving from one register - * to another, remove the association between the old register - * and the local. - */ - RegisterSpec previous - = primaryState.localItemToSpec(result.getLocalItem()); - - if (previous != null - && (previous.getReg() != result.getReg())) { - - primaryState.remove(previous); - } - - resultInfo.addAssignment(insn, result); - primaryState.put(result); - } - } - - primaryState.setImmutable(); - - /* - * Merge this state into the start state for each successor, - * and update the work set where required (that is, in cases - * where the start state for a block changes). - */ - - IntList successors = block.getSuccessors(); - int succSz = successors.size(); - int primarySuccessor = block.getPrimarySuccessor(); - - for (int i = 0; i < succSz; i++) { - int succ = successors.get(i); - RegisterSpecSet state = (succ == primarySuccessor) ? - primaryState : secondaryState; - - if (resultInfo.mergeStarts(succ, state)) { - Bits.set(workSet, succ); - } - } - } -} diff --git a/dx/src/com/android/dx/rop/code/LocalVariableInfo.java b/dx/src/com/android/dx/rop/code/LocalVariableInfo.java deleted file mode 100644 index 29c239b23..000000000 --- a/dx/src/com/android/dx/rop/code/LocalVariableInfo.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * 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.TypeBearer; -import com.android.dx.util.MutabilityControl; - -import java.util.HashMap; - -/** - * Container for local variable information for a particular {@link - * RopMethod}. - */ -public final class LocalVariableInfo - extends MutabilityControl { - /** >= 0; the register count for the method */ - private final int regCount; - - /** - * non-null; {@link RegisterSpecSet} to use when indicating a block - * that has no locals; it is empty and immutable but has an appropriate - * max size for the method - */ - private final RegisterSpecSet emptySet; - - /** - * non-null; array consisting of register sets representing the - * sets of variables already assigned upon entry to each block, - * where array indices correspond to block labels - */ - private final RegisterSpecSet[] blockStarts; - - /** non-null; map from instructions to the variable each assigns */ - private final HashMap<Insn, RegisterSpec> insnAssignments; - - /** - * Constructs an instance. - * - * @param method non-null; the method being represented by this instance - */ - public LocalVariableInfo(RopMethod method) { - if (method == null) { - throw new NullPointerException("method == null"); - } - - BasicBlockList blocks = method.getBlocks(); - int maxLabel = blocks.getMaxLabel(); - - this.regCount = blocks.getRegCount(); - this.emptySet = new RegisterSpecSet(regCount); - this.blockStarts = new RegisterSpecSet[maxLabel]; - this.insnAssignments = - new HashMap<Insn, RegisterSpec>(blocks.getInstructionCount()); - - emptySet.setImmutable(); - } - - /** - * Sets the register set associated with the start of the block with - * the given label. - * - * @param label >= 0; the block label - * @param specs non-null; the register set to associate with the block - */ - public void setStarts(int label, RegisterSpecSet specs) { - throwIfImmutable(); - - if (specs == null) { - throw new NullPointerException("specs == null"); - } - - try { - blockStarts[label] = specs; - } catch (ArrayIndexOutOfBoundsException ex) { - // Translate the exception. - throw new IllegalArgumentException("bogus label"); - } - } - - /** - * Merges the given register set into the set for the block with the - * given label. If there was not already an associated set, then this - * is the same as calling {@link #setStarts}. Otherwise, this will - * merge the two sets and call {@link #setStarts} on the result of the - * merge. - * - * @param label >= 0; the block label - * @param specs non-null; the register set to merge into the start set - * for the block - * @return <code>true</code> if the merge resulted in an actual change - * to the associated set (including storing one for the first time) or - * <code>false</code> if there was no change - */ - public boolean mergeStarts(int label, RegisterSpecSet specs) { - RegisterSpecSet start = getStarts0(label); - boolean changed = false; - - if (start == null) { - setStarts(label, specs); - return true; - } - - RegisterSpecSet newStart = start.mutableCopy(); - newStart.intersect(specs, true); - - if (start.equals(newStart)) { - return false; - } - - newStart.setImmutable(); - setStarts(label, newStart); - - return true; - } - - /** - * Gets the register set associated with the start of the block - * with the given label. This returns an empty set with the appropriate - * max size if no set was associated with the block in question. - * - * @param label >= 0; the block label - * @return non-null; the associated register set - */ - public RegisterSpecSet getStarts(int label) { - RegisterSpecSet result = getStarts0(label); - - return (result != null) ? result : emptySet; - } - - /** - * Gets the register set associated with the start of the given - * block. This is just convenient shorthand for - * <code>getStarts(block.getLabel())</code>. - * - * @param block non-null; the block in question - * @return non-null; the associated register set - */ - public RegisterSpecSet getStarts(BasicBlock block) { - return getStarts(block.getLabel()); - } - - /** - * Gets a mutable copy of the register set associated with the - * start of the block with the given label. This returns a - * newly-allocated empty {@link RegisterSpecSet} of appropriate - * max size if there is not yet any set associated with the block. - * - * @param label >= 0; the block label - * @return non-null; the associated register set - */ - public RegisterSpecSet mutableCopyOfStarts(int label) { - RegisterSpecSet result = getStarts0(label); - - return (result != null) ? - result.mutableCopy() : new RegisterSpecSet(regCount); - } - - /** - * Adds an assignment association for the given instruction and - * register spec. This throws an exception if the instruction - * doesn't actually perform a named variable assignment. - * - * <b>Note:</b> Although the instruction contains its own spec for - * the result, it still needs to be passed in explicitly to this - * method, since the spec that is stored here should always have a - * simple type and the one in the instruction can be an arbitrary - * {@link TypeBearer} (such as a constant value). - * - * @param insn non-null; the instruction in question - * @param spec non-null; the associated register spec - */ - public void addAssignment(Insn insn, RegisterSpec spec) { - throwIfImmutable(); - - if (insn == null) { - throw new NullPointerException("insn == null"); - } - - if (spec == null) { - throw new NullPointerException("spec == null"); - } - - insnAssignments.put(insn, spec); - } - - /** - * Gets the named register being assigned by the given instruction, if - * previously stored in this instance. - * - * @param insn non-null; instruction in question - * @return null-ok; the named register being assigned, if any - */ - public RegisterSpec getAssignment(Insn insn) { - return insnAssignments.get(insn); - } - - /** - * Gets the number of assignments recorded by this instance. - * - * @return >= 0; the number of assignments - */ - public int getAssignmentCount() { - return insnAssignments.size(); - } - - public void debugDump() { - for (int label = 0 ; label < blockStarts.length; label++) { - if (blockStarts[label] == null) { - continue; - } - - if (blockStarts[label] == emptySet) { - System.out.printf("%04x: empty set\n", label); - } else { - System.out.printf("%04x: %s\n", label, blockStarts[label]); - } - } - } - - /** - * Helper method, to get the starts for a label, throwing the - * right exception for range problems. - * - * @param label >= 0; the block label - * @return null-ok; associated register set or <code>null</code> if there - * is none - */ - private RegisterSpecSet getStarts0(int label) { - try { - return blockStarts[label]; - } catch (ArrayIndexOutOfBoundsException ex) { - // Translate the exception. - throw new IllegalArgumentException("bogus label"); - } - } -} diff --git a/dx/src/com/android/dx/rop/code/PlainCstInsn.java b/dx/src/com/android/dx/rop/code/PlainCstInsn.java deleted file mode 100644 index 908b3cb34..000000000 --- a/dx/src/com/android/dx/rop/code/PlainCstInsn.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.cst.Constant; -import com.android.dx.rop.type.StdTypeList; -import com.android.dx.rop.type.Type; -import com.android.dx.rop.type.TypeList; - -/** - * Instruction which contains an explicit reference to a constant - * but which cannot throw an exception. - */ -public final class PlainCstInsn - extends CstInsn { - /** - * Constructs an instance. - * - * @param opcode non-null; the opcode - * @param position non-null; source position - * @param result null-ok; spec for the result, if any - * @param sources non-null; specs for all the sources - * @param cst non-null; the constant - */ - public PlainCstInsn(Rop opcode, SourcePosition position, - RegisterSpec result, RegisterSpecList sources, - Constant cst) { - super(opcode, position, result, sources, cst); - - if (opcode.getBranchingness() != Rop.BRANCH_NONE) { - throw new IllegalArgumentException("bogus branchingness"); - } - } - - /** {@inheritDoc} */ - @Override - public TypeList getCatches() { - return StdTypeList.EMPTY; - } - - /** {@inheritDoc} */ - @Override - public void accept(Visitor visitor) { - visitor.visitPlainCstInsn(this); - } - - /** {@inheritDoc} */ - @Override - public Insn withAddedCatch(Type type) { - throw new UnsupportedOperationException("unsupported"); - } - - /** {@inheritDoc} */ - @Override - public Insn withRegisterOffset(int delta) { - return new PlainCstInsn(getOpcode(), getPosition(), - getResult().withOffset(delta), - getSources().withOffset(delta), - getConstant()); - } - - /** {@inheritDoc} */ - @Override - public Insn withNewRegisters(RegisterSpec result, - RegisterSpecList sources) { - - return new PlainCstInsn(getOpcode(), getPosition(), - result, - sources, - getConstant()); - - } -} diff --git a/dx/src/com/android/dx/rop/code/PlainInsn.java b/dx/src/com/android/dx/rop/code/PlainInsn.java deleted file mode 100644 index 4c5c9b701..000000000 --- a/dx/src/com/android/dx/rop/code/PlainInsn.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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.StdTypeList; -import com.android.dx.rop.type.Type; -import com.android.dx.rop.type.TypeList; -import com.android.dx.rop.type.TypeBearer; -import com.android.dx.rop.cst.Constant; - -/** - * Plain instruction, which has no embedded data and which cannot possibly - * throw an exception. - */ -public final class PlainInsn - extends Insn { - /** - * Constructs an instance. - * - * @param opcode non-null; the opcode - * @param position non-null; source position - * @param result null-ok; spec for the result, if any - * @param sources non-null; specs for all the sources - */ - public PlainInsn(Rop opcode, SourcePosition position, - RegisterSpec result, RegisterSpecList sources) { - super(opcode, position, result, sources); - - switch (opcode.getBranchingness()) { - case Rop.BRANCH_SWITCH: - case Rop.BRANCH_THROW: { - throw new IllegalArgumentException("bogus branchingness"); - } - } - - if (result != null && opcode.getBranchingness() != Rop.BRANCH_NONE) { - // move-result-pseudo is required here - throw new IllegalArgumentException - ("can't mix branchingness with result"); - } - } - - /** - * Constructs a single-source instance. - * - * @param opcode non-null; the opcode - * @param position non-null; source position - * @param result null-ok; spec for the result, if any - * @param source non-null; spec for the source - */ - public PlainInsn(Rop opcode, SourcePosition position, RegisterSpec result, - RegisterSpec source) { - this(opcode, position, result, RegisterSpecList.make(source)); - } - - /** {@inheritDoc} */ - @Override - public TypeList getCatches() { - return StdTypeList.EMPTY; - } - - /** {@inheritDoc} */ - @Override - public void accept(Visitor visitor) { - visitor.visitPlainInsn(this); - } - - /** {@inheritDoc} */ - @Override - public Insn withAddedCatch(Type type) { - throw new UnsupportedOperationException("unsupported"); - } - - /** {@inheritDoc} */ - @Override - public Insn withRegisterOffset(int delta) { - return new PlainInsn(getOpcode(), getPosition(), - getResult().withOffset(delta), - getSources().withOffset(delta)); - } - - /** {@inheritDoc} */ - @Override - public Insn withLastSourceLiteral() { - RegisterSpecList sources = getSources(); - int szSources = sources.size(); - - if (szSources == 0) { - return this; - } - - TypeBearer lastType = sources.get(szSources - 1).getTypeBearer(); - - if (!lastType.isConstant()) { - return this; - } - - Constant cst = (Constant) lastType; - - RegisterSpecList newSources = sources.withoutLast(); - - Rop newRop; - try { - newRop = Rops.ropFor(getOpcode().getOpcode(), - getResult(), newSources, (Constant)lastType); - } catch (IllegalArgumentException ex) { - // There's no rop for this case - return this; - } - - return new PlainCstInsn(newRop, getPosition(), - getResult(), newSources, cst); - } - - - /** {@inheritDoc} */ - @Override - public Insn withNewRegisters(RegisterSpec result, - RegisterSpecList sources) { - - return new PlainInsn(getOpcode(), getPosition(), - result, - sources); - - } -} diff --git a/dx/src/com/android/dx/rop/code/RegOps.java b/dx/src/com/android/dx/rop/code/RegOps.java deleted file mode 100644 index f201f68da..000000000 --- a/dx/src/com/android/dx/rop/code/RegOps.java +++ /dev/null @@ -1,403 +0,0 @@ -/* - * 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.util.Hex; - -/** - * All the register-based opcodes, and related utilities. - * - * <p><b>Note:</b> Opcode descriptions use a rough pseudocode. <code>r</code> - * is the result register, <code>x</code> is the first argument, - * <code>y</code> is the second argument, and <code>z</code> is the - * third argument. The expression which describes - * the operation uses Java-ish syntax but is preceded by type indicators for - * each of the values. - */ -public final class RegOps { - /** <code>nop()</code> */ - public static final int NOP = 1; - - /** <code>T: any type; r,x: T :: r = x;</code> */ - public static final int MOVE = 2; - - /** <code>T: any type; r,param(x): T :: r = param(x)</code> */ - public static final int MOVE_PARAM = 3; - - /** - * <code>T: Throwable; r: T :: r = caught_exception</code>. - * <b>Note:</b> This opcode should only ever be used in the - * first instruction of a block, and such blocks must be - * the start of an exception handler. - */ - public static final int MOVE_EXCEPTION = 4; - - /** <code>T: any type; r, literal: T :: r = literal;</code> */ - public static final int CONST = 5; - - /** <code>goto <i>label</i></code> */ - public static final int GOTO = 6; - - /** - * <code>T: int or Object; x,y: T :: if (x == y) goto - * <i>label</i></code> - */ - public static final int IF_EQ = 7; - - /** - * <code>T: int or Object; x,y: T :: if (x != y) goto - * <i>label</i></code> - */ - public static final int IF_NE = 8; - - /** <code>x,y: int :: if (x < y) goto <i>label</i></code> */ - public static final int IF_LT = 9; - - /** <code>x,y: int :: if (x >= y) goto <i>label</i></code> */ - public static final int IF_GE = 10; - - /** <code>x,y: int :: if (x <= y) goto <i>label</i></code> */ - public static final int IF_LE = 11; - - /** <code>x,y: int :: if (x > y) goto <i>label</i></code> */ - public static final int IF_GT = 12; - - /** <code>x: int :: goto <i>table[x]</i></code> */ - public static final int SWITCH = 13; - - /** <code>T: any numeric type; r,x,y: T :: r = x + y</code> */ - public static final int ADD = 14; - - /** <code>T: any numeric type; r,x,y: T :: r = x - y</code> */ - public static final int SUB = 15; - - /** <code>T: any numeric type; r,x,y: T :: r = x * y</code> */ - public static final int MUL = 16; - - /** <code>T: any numeric type; r,x,y: T :: r = x / y</code> */ - public static final int DIV = 17; - - /** - * <code>T: any numeric type; r,x,y: T :: r = x % y</code> - * (Java-style remainder) - */ - public static final int REM = 18; - - /** <code>T: any numeric type; r,x: T :: r = -x</code> */ - public static final int NEG = 19; - - /** <code>T: any integral type; r,x,y: T :: r = x & y</code> */ - public static final int AND = 20; - - /** <code>T: any integral type; r,x,y: T :: r = x | y</code> */ - public static final int OR = 21; - - /** <code>T: any integral type; r,x,y: T :: r = x ^ y</code> */ - public static final int XOR = 22; - - /** - * <code>T: any integral type; r,x: T; y: int :: r = x << - * y</code> - */ - public static final int SHL = 23; - - /** - * <code>T: any integral type; r,x: T; y: int :: r = x >> - * y</code> (signed right-shift) - */ - public static final int SHR = 24; - - /** - * <code>T: any integral type; r,x: T; y: int :: r = x - * >>> y</code> (unsigned right-shift) - */ - public static final int USHR = 25; - - /** <code>T: any integral type; r,x: T :: r = ~x</code> */ - public static final int NOT = 26; - - /** - * <code>T: any numeric type; r: int; x,y: T :: r = (x == y) ? 0 - * : (x > y) ? 1 : -1</code> (Java-style "cmpl" where a NaN is - * considered "less than" all other values; also used for integral - * comparisons) - */ - public static final int CMPL = 27; - - /** - * <code>T: any floating point type; r: int; x,y: T :: r = (x == y) ? 0 - * : (x < y) ? -1 : 1</code> (Java-style "cmpg" where a NaN is - * considered "greater than" all other values) - */ - public static final int CMPG = 28; - - /** - * <code>T: any numeric type; U: any numeric type; r: T; x: U :: - * r = (T) x</code> (numeric type conversion between the four - * "real" numeric types) - */ - public static final int CONV = 29; - - /** - * <code>r,x: int :: r = (x << 24) >> 24</code> (Java-style - * convert int to byte) - */ - public static final int TO_BYTE = 30; - - /** - * <code>r,x: int :: r = x & 0xffff</code> (Java-style - * convert int to char) - */ - public static final int TO_CHAR = 31; - - /** - * <code>r,x: int :: r = (x << 16) >> 16</code> (Java-style - * convert int to short) - */ - public static final int TO_SHORT = 32; - - /** <code>T: return type for the method; x: T; return x</code> */ - public static final int RETURN = 33; - - /** <code>T: any type; r: int; x: T[]; :: r = x.length</code> */ - public static final int ARRAY_LENGTH = 34; - - /** <code>x: Throwable :: throw(x)</code> */ - public static final int THROW = 35; - - /** <code>x: Object :: monitorenter(x)</code> */ - public static final int MONITOR_ENTER = 36; - - /** <code>x: Object :: monitorexit(x)</code> */ - public static final int MONITOR_EXIT = 37; - - /** <code>T: any type; r: T; x: T[]; y: int :: r = x[y]</code> */ - public static final int AGET = 38; - - /** <code>T: any type; x: T; y: T[]; z: int :: x[y] = z</code> */ - public static final int APUT = 39; - - /** - * <code>T: any non-array object type :: r = - * alloc(T)</code> (allocate heap space for an object) - */ - public static final int NEW_INSTANCE = 40; - - /** <code>T: any array type; r: T; x: int :: r = new T[x]</code> */ - public static final int NEW_ARRAY = 41; - - /** - * <code>T: any array type; r: T; x: int; v0..vx: T :: r = new T[x] - * {v0, ..., vx}</code> - */ - public static final int FILLED_NEW_ARRAY = 42; - - /** - * <code>T: any object type; x: Object :: (T) x</code> (can - * throw <code>ClassCastException</code>) - */ - public static final int CHECK_CAST = 43; - - /** - * <code>T: any object type; x: Object :: x instanceof - * T</code> - */ - public static final int INSTANCE_OF = 44; - - /** - * <code>T: any type; r: T; x: Object; f: instance field spec of - * type T :: r = x.f</code> - */ - public static final int GET_FIELD = 45; - - /** - * <code>T: any type; r: T; f: static field spec of type T :: r = - * f</code> - */ - public static final int GET_STATIC = 46; - - /** - * <code>T: any type; x: T; y: Object; f: instance field spec of type - * T :: y.f = x</code> - */ - public static final int PUT_FIELD = 47; - - /** - * <code>T: any type; f: static field spec of type T; x: T :: f = - * x</code> - */ - public static final int PUT_STATIC = 48; - - /** - * <code>Tr, T0, T1...: any types; r: Tr; m: static method spec; - * y0: T0; y1: T1 ... :: r = m(y0, y1, ...)</code> (call static - * method) - */ - public static final int INVOKE_STATIC = 49; - - /** - * <code>Tr, T0, T1...: any types; r: Tr; x: Object; m: instance method - * spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1, ...)</code> (call normal - * virtual method) - */ - public static final int INVOKE_VIRTUAL = 50; - - /** - * <code>Tr, T0, T1...: any types; r: Tr; x: Object; m: instance method - * spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1, ...)</code> (call - * superclass virtual method) - */ - public static final int INVOKE_SUPER = 51; - - /** - * <code>Tr, T0, T1...: any types; r: Tr; x: Object; m: instance method - * spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1, ...)</code> (call - * direct/special method) - */ - public static final int INVOKE_DIRECT = 52; - - /** - * <code>Tr, T0, T1...: any types; r: Tr; x: Object; m: interface - * (instance) method spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1, - * ...)</code> (call interface method) - */ - public static final int INVOKE_INTERFACE = 53; - - /** - * <code> T0: any type; </code> (mark beginning or end of local variable - * name - */ - public static final int MARK_LOCAL = 54; - - /** - * <code>T: Any type; r: T :: r = return_type</code>. - * <b>Note:</b> This opcode should only ever be used in the - * first instruction of a block following an invoke-*. - */ - public static final int MOVE_RESULT = 55; - - /** - * <code>T: Any type; r: T :: r = return_type</code>. - * <b>Note:</b> This opcode should only ever be used in the - * first instruction of a block following a non-invoke throwing insn - */ - public static final int MOVE_RESULT_PSEUDO = 56; - - /** <code>T: Any primitive type; v0..vx: T :: {v0, ..., vx}</code> */ - public static final int FILL_ARRAY_DATA = 57; - - /** - * This class is uninstantiable. - */ - private RegOps() { - // This space intentionally left blank. - } - - /** - * Gets the name of the given opcode. - * - * @param opcode >= 0, <= 255; the opcode - * @return non-null; its name - */ - public static String opName(int opcode) { - switch (opcode) { - case NOP: return "nop"; - case MOVE: return "move"; - case MOVE_PARAM: return "move-param"; - case MOVE_EXCEPTION: return "move-exception"; - case CONST: return "const"; - case GOTO: return "goto"; - case IF_EQ: return "if-eq"; - case IF_NE: return "if-ne"; - case IF_LT: return "if-lt"; - case IF_GE: return "if-ge"; - case IF_LE: return "if-le"; - case IF_GT: return "if-gt"; - case SWITCH: return "switch"; - case ADD: return "add"; - case SUB: return "sub"; - case MUL: return "mul"; - case DIV: return "div"; - case REM: return "rem"; - case NEG: return "neg"; - case AND: return "and"; - case OR: return "or"; - case XOR: return "xor"; - case SHL: return "shl"; - case SHR: return "shr"; - case USHR: return "ushr"; - case NOT: return "not"; - case CMPL: return "cmpl"; - case CMPG: return "cmpg"; - case CONV: return "conv"; - case TO_BYTE: return "to-byte"; - case TO_CHAR: return "to-char"; - case TO_SHORT: return "to-short"; - case RETURN: return "return"; - case ARRAY_LENGTH: return "array-length"; - case THROW: return "throw"; - case MONITOR_ENTER: return "monitor-enter"; - case MONITOR_EXIT: return "monitor-exit"; - case AGET: return "aget"; - case APUT: return "aput"; - case NEW_INSTANCE: return "new-instance"; - case NEW_ARRAY: return "new-array"; - case FILLED_NEW_ARRAY: return "filled-new-array"; - case CHECK_CAST: return "check-cast"; - case INSTANCE_OF: return "instance-of"; - case GET_FIELD: return "get-field"; - case GET_STATIC: return "get-static"; - case PUT_FIELD: return "put-field"; - case PUT_STATIC: return "put-static"; - case INVOKE_STATIC: return "invoke-static"; - case INVOKE_VIRTUAL: return "invoke-virtual"; - case INVOKE_SUPER: return "invoke-super"; - case INVOKE_DIRECT: return "invoke-direct"; - case INVOKE_INTERFACE: return "invoke-interface"; - case MOVE_RESULT: return "move-result"; - case MOVE_RESULT_PSEUDO: return "move-result-pseudo"; - case FILL_ARRAY_DATA: return "fill-array-data"; - } - - return "unknown-" + Hex.u1(opcode); - } - - /** - * Given an IF_* RegOp, returns the right-to-left flipped version. For - * example, IF_GT becomes IF_LT. - * - * @param opcode An IF_* RegOp - * @return flipped IF Regop - */ - public static int flippedIfOpcode(final int opcode) { - switch (opcode) { - case RegOps.IF_EQ: - case RegOps.IF_NE: - return opcode; - case RegOps.IF_LT: - return RegOps.IF_GT; - case RegOps.IF_GE: - return RegOps.IF_LE; - case RegOps.IF_LE: - return RegOps.IF_GE; - case RegOps.IF_GT: - return RegOps.IF_LT; - default: - throw new RuntimeException("Unrecognized IF regop: " + opcode); - } - } -} diff --git a/dx/src/com/android/dx/rop/code/RegisterSpec.java b/dx/src/com/android/dx/rop/code/RegisterSpec.java deleted file mode 100644 index 09f7f1829..000000000 --- a/dx/src/com/android/dx/rop/code/RegisterSpec.java +++ /dev/null @@ -1,552 +0,0 @@ -/* - * 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.cst.Constant; -import com.android.dx.rop.cst.CstUtf8; -import com.android.dx.rop.type.Type; -import com.android.dx.rop.type.TypeBearer; -import com.android.dx.util.ToHuman; - -import java.util.HashMap; - -/** - * Combination of a register number and a type, used as the sources and - * destinations of register-based operations. - */ -public final class RegisterSpec - implements TypeBearer, ToHuman { - /** non-null; string to prefix register numbers with */ - public static final String PREFIX = "v"; - - /** non-null; intern table for instances */ - private static final HashMap<Object, RegisterSpec> theInterns = - new HashMap<Object, RegisterSpec>(1000); - - /** non-null; common comparison instance used while interning */ - private static final ForComparison theInterningItem = new ForComparison(); - - /** >= 0; register number */ - private final int reg; - - /** non-null; type loaded or stored */ - private final TypeBearer type; - - /** null-ok; local variable info associated with this register, if any */ - private final LocalItem local; - - /** - * Intern the given triple as an instance of this class. - * - * @param reg >= 0; the register number - * @param type non-null; the type (or possibly actual value) which - * is loaded from or stored to the indicated register - * @param local null-ok; the associated local variable, if any - * @return non-null; an appropriately-constructed instance - */ - private static RegisterSpec intern(int reg, TypeBearer type, - LocalItem local) { - theInterningItem.set(reg, type, local); - RegisterSpec found = theInterns.get(theInterningItem); - - if (found != null) { - return found; - } - - found = theInterningItem.toRegisterSpec(); - theInterns.put(found, found); - return found; - } - - /** - * Returns an instance for the given register number and type, with - * no variable info. This method is allowed to return shared - * instances (but doesn't necessarily do so). - * - * @param reg >= 0; the register number - * @param type non-null; the type (or possibly actual value) which - * is loaded from or stored to the indicated register - * @return non-null; an appropriately-constructed instance - */ - public static RegisterSpec make(int reg, TypeBearer type) { - return intern(reg, type, null); - } - - /** - * Returns an instance for the given register number, type, and - * variable info. This method is allowed to return shared - * instances (but doesn't necessarily do so). - * - * @param reg >= 0; the register number - * @param type non-null; the type (or possibly actual value) which - * is loaded from or stored to the indicated register - * @param local non-null; the associated local variable - * @return non-null; an appropriately-constructed instance - */ - public static RegisterSpec make(int reg, TypeBearer type, LocalItem local) { - if (local == null) { - throw new NullPointerException("local == null"); - } - - return intern(reg, type, local); - } - - /** - * Returns an instance for the given register number, type, and - * variable info. This method is allowed to return shared - * instances (but doesn't necessarily do so). - * - * @param reg >= 0; the register number - * @param type non-null; the type (or possibly actual value) which - * is loaded from or stored to the indicated register - * @param local null-ok; the associated variable info or null for - * none - * @return non-null; an appropriately-constructed instance - */ - public static RegisterSpec makeLocalOptional( - int reg, TypeBearer type, LocalItem local) { - - return intern(reg, type, local); - } - - /** - * Gets the string form for the given register number. - * - * @param reg >= 0; the register number - * @return non-null; the string form - */ - public static String regString(int reg) { - return PREFIX + reg; - } - - /** - * Constructs an instance. This constructor is private. Use - * {@link #make}. - * - * @param reg >= 0; the register number - * @param type non-null; the type (or possibly actual value) which - * is loaded from or stored to the indicated register - * @param local null-ok; the associated local variable, if any - */ - private RegisterSpec(int reg, TypeBearer type, LocalItem local) { - if (reg < 0) { - throw new IllegalArgumentException("reg < 0"); - } - - if (type == null) { - throw new NullPointerException("type == null"); - } - - this.reg = reg; - this.type = type; - this.local = local; - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - if (!(other instanceof RegisterSpec)) { - if (other instanceof ForComparison) { - ForComparison fc = (ForComparison) other; - return equals(fc.reg, fc.type, fc.local); - } - return false; - } - - RegisterSpec spec = (RegisterSpec) other; - return equals(spec.reg, spec.type, spec.local); - } - - /** - * Helper for {@link #equals} and {@link #ForComparison.equals}, - * which actually does the test. - * - * @param reg value of the instance variable, for another instance - * @param type value of the instance variable, for another instance - * @param local value of the instance variable, for another instance - * @return whether this instance is equal to one with the given - * values - */ - private boolean equals(int reg, TypeBearer type, LocalItem local) { - return (this.reg == reg) - && this.type.equals(type) - && ((this.local == local) - || ((this.local != null) && this.local.equals(local))); - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - return hashCodeOf(reg, type, local); - } - - /** - * Helper for {@link #hashCode} and {@link #ForComparison.hashCode}, - * which actually does the calculation. - * - * @param reg value of the instance variable - * @param type value of the instance variable - * @param local value of the instance variable - * @return the hash code - */ - private static int hashCodeOf(int reg, TypeBearer type, LocalItem local) { - int hash = (local != null) ? local.hashCode() : 0; - - hash = (hash * 31 + type.hashCode()) * 31 + reg; - return hash; - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return toString0(false); - } - - /** {@inheritDoc} */ - public String toHuman() { - return toString0(true); - } - - /** {@inheritDoc} */ - public Type getType() { - return type.getType(); - } - - /** {@inheritDoc} */ - public TypeBearer getFrameType() { - return type.getFrameType(); - } - - /** {@inheritDoc} */ - public final int getBasicType() { - return type.getBasicType(); - } - - /** {@inheritDoc} */ - public final int getBasicFrameType() { - return type.getBasicFrameType(); - } - - /** {@inheritDoc} */ - public final boolean isConstant() { - return false; - } - - /** - * Gets the register number. - * - * @return >= 0; the register number - */ - public int getReg() { - return reg; - } - - /** - * Gets the type (or actual value) which is loaded from or stored - * to the register associated with this instance. - * - * @return non-null; the type - */ - public TypeBearer getTypeBearer() { - return type; - } - - /** - * Gets the variable info associated with this instance, if any. - * - * @return null-ok; the variable info, or <code>null</code> if this - * instance has none - */ - public LocalItem getLocalItem() { - return local; - } - - /** - * Gets the next available register number after the one in this - * instance. This is equal to the register number plus the width - * (category) of the type used. Among other things, this may also - * be used to determine the minimum required register count - * implied by this instance. - * - * @return >= 0; the required registers size - */ - public int getNextReg() { - return reg + getCategory(); - } - - /** - * Gets the category of this instance's type. This is just a convenient - * shorthand for <code>getType().getCategory()</code>. - * - * @return 1..2; the category of this instance's type - */ - public int getCategory() { - return type.getType().getCategory(); - } - - /** - * Gets the string form for just the register number of this instance. - * - * @return non-null; the register string form - */ - public String regString() { - return regString(reg); - } - - /** - * Returns an instance that is the intersection between this instance - * and the given one, if any. The intersection is defined as follows: - * - * <ul> - * <li>If <code>other</code> is <code>null</code>, then the result - * is <code>null</code>. - * <li>If the register numbers don't match, then the intersection - * is <code>null</code>. Otherwise, the register number of the - * intersection is the same as the one in the two instances.</li> - * <li>If the types returned by <code>getType()</code> are not - * <code>equals()</code>, then the intersection is null.</li> - * <li>If the type bearers returned by <code>getTypeBearer()</code> - * are <code>equals()</code>, then the intersection's type bearer - * is the one from this instance. Otherwise, the intersection's - * type bearer is the <code>getType()</code> of this instance.</li> - * <li>If the locals are <code>equals()</code>, then the local info of the - * intersection is the local info of this instance. Otherwise, the local info - * of the intersection is <code>null</code>.</li> - * </ul> - * - * @param other null-ok; instance to intersect with (or <code>null</code>) - * @param localPrimary whether local variables are primary to - * the intersection; if <code>true</code>, then the only non-null - * results occur when registers being intersected have equal local infos (or - * both have <code>null</code> local infos) - * @return null-ok; the intersection - */ - public RegisterSpec intersect(RegisterSpec other, boolean localPrimary) { - if (this == other) { - // Easy out. - return this; - } - - if ((other == null) || (reg != other.getReg())) { - return null; - } - - LocalItem resultLocal = - ((local == null) || !local.equals(other.getLocalItem())) ? null : local; - boolean sameName = (resultLocal == local); - - if (localPrimary && !sameName) { - return null; - } - - Type thisType = getType(); - Type otherType = other.getType(); - - // Note: Types are always interned. - if (thisType != otherType) { - return null; - } - - TypeBearer resultTypeBearer = - type.equals(other.getTypeBearer()) ? type : thisType; - - if ((resultTypeBearer == type) && sameName) { - // It turns out that the intersection is "this" after all. - return this; - } - - return (resultLocal == null) ? make(reg, resultTypeBearer) : - make(reg, resultTypeBearer, resultLocal); - } - - /** - * Returns an instance that is identical to this one, except that the - * register number is replaced by the given one. - * - * @param newReg >= 0; the new register number - * @return non-null; an appropriately-constructed instance - */ - public RegisterSpec withReg(int newReg) { - if (reg == newReg) { - return this; - } - - return makeLocalOptional(newReg, type, local); - } - - /** - * Returns an instance that is identical to this one, except that - * the type is replaced by the given one. - * - * @param newType non-null; the new type - * @return non-null; an appropriately-constructed instance - */ - public RegisterSpec withType(TypeBearer newType) { - return makeLocalOptional(reg, newType, local); - } - - /** - * Returns an instance that is identical to this one, except that the - * register number is offset by the given amount. - * - * @param delta the amount to offset the register number by - * @return non-null; an appropriately-constructed instance - */ - public RegisterSpec withOffset(int delta) { - if (delta == 0) { - return this; - } - - return withReg(reg + delta); - } - - /** - * Returns an instance that is identical to this one, except that - * the type bearer is replaced by the actual underlying type - * (thereby stripping off non-type information) with any - * initialization information stripped away as well. - * - * @return non-null; an appropriately-constructed instance - */ - public RegisterSpec withSimpleType() { - TypeBearer orig = type; - Type newType; - - if (orig instanceof Type) { - newType = (Type) orig; - } else { - newType = orig.getType(); - } - - if (newType.isUninitialized()) { - newType = newType.getInitializedType(); - } - - if (newType == orig) { - return this; - } - - return makeLocalOptional(reg, newType, local); - } - - /** - * Returns an instance that is identical to this one except that the - * local variable is as specified in the parameter. - * - * @param local null-ok; the local item or null for none - * @return an appropriate instance - */ - public RegisterSpec withLocalItem(LocalItem local) { - if ((this.local== local) - || ((this.local != null) && this.local.equals(local))) { - - return this; - } - - return makeLocalOptional(reg, type, local); - } - - - /** - * Helper for {@link #toString} and {@link #toHuman}. - * - * @param human whether to be human-oriented - * @return non-null; the string form - */ - private String toString0(boolean human) { - StringBuffer sb = new StringBuffer(40); - - sb.append(regString()); - sb.append(":"); - - if (local != null) { - sb.append(local.toString()); - } - - Type justType = type.getType(); - sb.append(justType); - - if (justType != type) { - sb.append("="); - if (human && (type instanceof Constant)) { - sb.append(((Constant) type).toHuman()); - } else { - sb.append(type); - } - } - - return sb.toString(); - } - - /** - * Holder of register spec data for the purposes of comparison (so that - * <code>RegisterSpec</code> itself can still keep <code>final</code> - * instance variables. - */ - private static class ForComparison { - /** >= 0; register number */ - private int reg; - - /** non-null; type loaded or stored */ - private TypeBearer type; - - /** null-ok; local variable associated with this register, if any */ - private LocalItem local; - - /** - * Set all the instance variables. - * - * @param reg >= 0; the register number - * @param type non-null; the type (or possibly actual value) which - * is loaded from or stored to the indicated register - * @param local null-ok; the associated local variable, if any - * @return non-null; an appropriately-constructed instance - */ - public void set(int reg, TypeBearer type, LocalItem local) { - this.reg = reg; - this.type = type; - this.local = local; - } - - /** - * Construct a <code>RegisterSpec</code> of this instance's - * contents. - * - * @return non-null; an appropriately-constructed instance - */ - public RegisterSpec toRegisterSpec() { - return new RegisterSpec(reg, type, local); - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - if (!(other instanceof RegisterSpec)) { - return false; - } - - RegisterSpec spec = (RegisterSpec) other; - return spec.equals(reg, type, local); - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - return hashCodeOf(reg, type, local); - } - } -} diff --git a/dx/src/com/android/dx/rop/code/RegisterSpecList.java b/dx/src/com/android/dx/rop/code/RegisterSpecList.java deleted file mode 100644 index 28657a197..000000000 --- a/dx/src/com/android/dx/rop/code/RegisterSpecList.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * 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; - -/** - * List of {@link RegisterSpec} instances. - */ -public final class RegisterSpecList - extends FixedSizeList implements TypeList { - /** non-null; no-element instance */ - public static final RegisterSpecList EMPTY = new RegisterSpecList(0); - - /** - * Makes a single-element instance. - * - * @param spec non-null; the element - * @return 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 non-null; the first element - * @param spec1 non-null; the second element - * @return 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 non-null; the first element - * @param spec1 non-null; the second element - * @param spec2 non-null; the third element - * @return 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 non-null; the first element - * @param spec1 non-null; the second element - * @param spec2 non-null; the third element - * @param spec3 non-null; the fourth element - * @return 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</code>. - * - * @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</code>. - * - * @param n >= 0, < size(); which element - * @return 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 >= 0, < size(); which element - * @param spec 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 >= 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 non-null; the new first spec (to prepend) - * @return 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 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 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 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 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 register numbers are renumbered sequentially from the given - * base, with the first number duplicated if indicated. - * - * @param base the base register number - * @param duplicateFirst whether to duplicate the first number - * @return non-null; an appropriately-constructed instance - */ - public RegisterSpecList withSequentialRegisters(int base, - boolean duplicateFirst) { - 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); - result.set0(i, one.withReg(base)); - if (duplicateFirst) { - duplicateFirst = false; - } else { - base += one.getCategory(); - } - } - - if (isImmutable()) { - result.setImmutable(); - } - - return result; - } - -} diff --git a/dx/src/com/android/dx/rop/code/RegisterSpecSet.java b/dx/src/com/android/dx/rop/code/RegisterSpecSet.java deleted file mode 100644 index 4eb2f65e8..000000000 --- a/dx/src/com/android/dx/rop/code/RegisterSpecSet.java +++ /dev/null @@ -1,350 +0,0 @@ -/* - * 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.util.MutabilityControl; -import com.android.dx.rop.cst.CstUtf8; - -/** - * Set of {@link RegisterSpec} instances, where a given register number - * may appear only once in the set. - */ -public final class RegisterSpecSet - extends MutabilityControl { - /** non-null; no-element instance */ - public static final RegisterSpecSet EMPTY = new RegisterSpecSet(0); - - /** - * non-null; array of register specs, where each element is - * <code>null</code> or is an instance whose <code>reg</code> - * matches the array index - */ - private final RegisterSpec[] specs; - - /** >= -1; size of the set or <code>-1</code> if not yet calculated */ - private int size; - - /** - * Constructs an instance. The instance is initially empty. - * - * @param maxSize >= 0; the maximum register number (exclusive) that - * may be represented in this instance - */ - public RegisterSpecSet(int maxSize) { - super(maxSize != 0); - - this.specs = new RegisterSpec[maxSize]; - this.size = 0; - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - if (!(other instanceof RegisterSpecSet)) { - return false; - } - - RegisterSpecSet otherSet = (RegisterSpecSet) other; - RegisterSpec[] otherSpecs = otherSet.specs; - int len = specs.length; - - if ((len != otherSpecs.length) || (size() != otherSet.size())) { - return false; - } - - for (int i = 0; i < len; i++) { - RegisterSpec s1 = specs[i]; - RegisterSpec s2 = otherSpecs[i]; - - if (s1 == s2) { - continue; - } - - if ((s1 == null) || !s1.equals(s2)) { - return false; - } - } - - return true; - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - int len = specs.length; - int hash = 0; - - for (int i = 0; i < len; i++) { - RegisterSpec spec = specs[i]; - int oneHash = (spec == null) ? 0 : spec.hashCode(); - hash = (hash * 31) + oneHash; - } - - return hash; - } - - /** {@inheritDoc} */ - @Override - public String toString() { - int len = specs.length; - StringBuffer sb = new StringBuffer(len * 25); - - sb.append('{'); - - boolean any = false; - for (int i = 0; i < len; i++) { - RegisterSpec spec = specs[i]; - if (spec != null) { - if (any) { - sb.append(", "); - } else { - any = true; - } - sb.append(spec); - } - } - - sb.append('}'); - return sb.toString(); - } - - /** - * Gets the maximum number of registers that may be in this instance, which - * is also the maximum-plus-one of register numbers that may be - * represented. - * - * @return >= 0; the maximum size - */ - public int getMaxSize() { - return specs.length; - } - - /** - * Gets the current size of this instance. - * - * @return >= 0; the size - */ - public int size() { - int result = size; - - if (result < 0) { - int len = specs.length; - - result = 0; - for (int i = 0; i < len; i++) { - if (specs[i] != null) { - result++; - } - } - - size = result; - } - - return result; - } - - /** - * Gets the element with the given register number, if any. - * - * @param reg >= 0; the desired register number - * @return null-ok; the element with the given register number or - * <code>null</code> if there is none - */ - public RegisterSpec get(int reg) { - try { - return specs[reg]; - } catch (ArrayIndexOutOfBoundsException ex) { - // Translate the exception. - throw new IllegalArgumentException("bogus reg"); - } - } - - /** - * Gets the element with the same register number as the given - * spec, if any. This is just a convenient shorthand for - * <code>get(spec.getReg())</code>. - * - * @param spec non-null; spec with the desired register number - * @return null-ok; the element with the matching register number or - * <code>null</code> if there is none - */ - public RegisterSpec get(RegisterSpec spec) { - return get(spec.getReg()); - } - - /** - * Returns the spec in this set that's currently associated with a given - * name, or null if there is none. - * - * @param local non-null; local item to search for - * @return null-ok; first register found with name. - */ - public RegisterSpec localItemToSpec(LocalItem local) { - for (int reg = 0; reg < specs.length; reg++) { - if (specs[reg] != null && local.equals(specs[reg].getLocalItem())) { - return specs[reg]; - } - } - - return null; - } - - /** - * Removes a spec from the set. Only the register number - * of the parameter is significant. - * - * @param toRemove non-null; register to remove. - */ - public void remove(RegisterSpec toRemove) { - try { - specs[toRemove.getReg()] = null; - size = -1; - } catch (ArrayIndexOutOfBoundsException ex) { - // Translate the exception. - throw new IllegalArgumentException("bogus reg"); - } - } - - /** - * Puts the given spec into the set. If there is already an element in - * the set with the same register number, it is replaced. Additionally, - * if the previous element is for a category-2 register, then that - * previous element is nullified. Finally, if the given spec is for - * a category-2 register, then the immediately subsequent element - * is nullified. - * - * @param spec non-null; the register spec to put in the instance - */ - public void put(RegisterSpec spec) { - throwIfImmutable(); - - if (spec == null) { - throw new NullPointerException("spec == null"); - } - - size = -1; - - try { - int reg = spec.getReg(); - specs[reg] = spec; - - if (reg > 0) { - int prevReg = reg - 1; - RegisterSpec prevSpec = specs[prevReg]; - if ((prevSpec != null) && (prevSpec.getCategory() == 2)) { - specs[prevReg] = null; - } - } - - if (spec.getCategory() == 2) { - specs[reg + 1] = null; - } - } catch (ArrayIndexOutOfBoundsException ex) { - // Translate the exception. - throw new IllegalArgumentException("spec.getReg() out of range"); - } - } - - /** - * Intersects this instance with the given one, modifying this - * instance. The intersection consists of the pairwise - * {@link RegisterSpec#intersect} of corresponding elements from - * this instance and the given one where both are non-null. - * - * @param other non-null; set to intersect with - * @param localPrimary whether local variables are primary to - * the intersection; if <code>true</code>, then the only non-null - * result elements occur when registers being intersected have - * equal names (or both have <code>null</code> names) - */ - public void intersect(RegisterSpecSet other, boolean localPrimary) { - throwIfImmutable(); - - RegisterSpec[] otherSpecs = other.specs; - int thisLen = specs.length; - int len = Math.min(thisLen, otherSpecs.length); - - size = -1; - - for (int i = 0; i < len; i++) { - RegisterSpec spec = specs[i]; - - if (spec == null) { - continue; - } - - RegisterSpec intersection = - spec.intersect(otherSpecs[i], localPrimary); - if (intersection != spec) { - specs[i] = intersection; - } - } - - for (int i = len; i < thisLen; i++) { - specs[i] = null; - } - } - - /** - * 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 non-null; an appropriately-constructed instance - */ - public RegisterSpecSet withOffset(int delta) { - int len = specs.length; - RegisterSpecSet result = new RegisterSpecSet(len + delta); - - for (int i = 0; i < len; i++) { - RegisterSpec spec = specs[i]; - if (spec != null) { - result.put(spec.withOffset(delta)); - } - } - - result.size = size; - - if (isImmutable()) { - result.setImmutable(); - } - - return result; - } - - /** - * Makes and return a mutable copy of this instance. - * - * @return non-null; the mutable copy - */ - public RegisterSpecSet mutableCopy() { - int len = specs.length; - RegisterSpecSet copy = new RegisterSpecSet(len); - - for (int i = 0; i < len; i++) { - RegisterSpec spec = specs[i]; - if (spec != null) { - copy.put(spec); - } - } - - copy.size = size; - - return copy; - } -} diff --git a/dx/src/com/android/dx/rop/code/Rop.java b/dx/src/com/android/dx/rop/code/Rop.java deleted file mode 100644 index f918e126c..000000000 --- a/dx/src/com/android/dx/rop/code/Rop.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * 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.StdTypeList; -import com.android.dx.rop.type.Type; -import com.android.dx.rop.type.TypeList; -import com.android.dx.util.Hex; - -/** - * Class that describes all the immutable parts of register-based operations. - */ -public final class Rop { - /** minimum <code>BRANCH_*</code> value */ - public static final int BRANCH_MIN = 1; - - /** indicates a non-branching op */ - public static final int BRANCH_NONE = 1; - - /** indicates a function/method return */ - public static final int BRANCH_RETURN = 2; - - /** indicates an unconditional goto */ - public static final int BRANCH_GOTO = 3; - - /** indicates a two-way branch */ - public static final int BRANCH_IF = 4; - - /** indicates a switch-style branch */ - public static final int BRANCH_SWITCH = 5; - - /** indicates a throw-style branch (both always-throws and may-throw) */ - public static final int BRANCH_THROW = 6; - - /** maximum <code>BRANCH_*</code> value */ - public static final int BRANCH_MAX = 6; - - /** the opcode; one of the constants in {@link RegOps} */ - private final int opcode; - - /** - * non-null; result type of this operation; {@link Type#VOID} for - * no-result operations - */ - private final Type result; - - /** non-null; types of all the sources of this operation */ - private final TypeList sources; - - /** non-null; list of possible types thrown by this operation */ - private final TypeList exceptions; - - /** - * the branchingness of this op; one of the <code>BRANCH_*</code> - * constants in this class - */ - private final int branchingness; - - /** whether this is a function/method call op or similar */ - private final boolean isCallLike; - - /** null-ok; nickname, if specified (used for debugging) */ - private final String nickname; - - /** - * Constructs an instance. This method is private. Use one of the - * public constructors. - * - * @param opcode the opcode; one of the constants in {@link RegOps} - * @param result non-null; result type of this operation; {@link - * Type#VOID} for no-result operations - * @param sources non-null; types of all the sources of this operation - * @param exceptions non-null; list of possible types thrown by this - * operation - * @param branchingness the branchingness of this op; one of the - * <code>BRANCH_*</code> constants - * @param isCallLike whether the op is a function/method call or similar - * @param nickname null-ok; optional nickname (used for debugging) - */ - public Rop(int opcode, Type result, TypeList sources, - TypeList exceptions, int branchingness, boolean isCallLike, - String nickname) { - if (result == null) { - throw new NullPointerException("result == null"); - } - - if (sources == null) { - throw new NullPointerException("sources == null"); - } - - if (exceptions == null) { - throw new NullPointerException("exceptions == null"); - } - - if ((branchingness < BRANCH_MIN) || (branchingness > BRANCH_MAX)) { - throw new IllegalArgumentException("bogus branchingness"); - } - - if ((exceptions.size() != 0) && (branchingness != BRANCH_THROW)) { - throw new IllegalArgumentException("exceptions / branchingness " + - "mismatch"); - } - - this.opcode = opcode; - this.result = result; - this.sources = sources; - this.exceptions = exceptions; - this.branchingness = branchingness; - this.isCallLike = isCallLike; - this.nickname = nickname; - } - - /** - * Constructs an instance. The constructed instance is never a - * call-like op (see {@link #isCallLike}). - * - * @param opcode the opcode; one of the constants in {@link RegOps} - * @param result non-null; result type of this operation; {@link - * Type#VOID} for no-result operations - * @param sources non-null; types of all the sources of this operation - * @param exceptions non-null; list of possible types thrown by this - * operation - * @param branchingness the branchingness of this op; one of the - * <code>BRANCH_*</code> constants - * @param nickname null-ok; optional nickname (used for debugging) - */ - public Rop(int opcode, Type result, TypeList sources, - TypeList exceptions, int branchingness, String nickname) { - this(opcode, result, sources, exceptions, branchingness, false, - nickname); - } - - /** - * Constructs a no-exception instance. The constructed instance is never a - * call-like op (see {@link #isCallLike}). - * - * @param opcode the opcode; one of the constants in {@link RegOps} - * @param result non-null; result type of this operation; {@link - * Type#VOID} for no-result operations - * @param sources non-null; types of all the sources of this operation - * @param branchingness the branchingness of this op; one of the - * <code>BRANCH_*</code> constants - * @param nickname null-ok; optional nickname (used for debugging) - */ - public Rop(int opcode, Type result, TypeList sources, int branchingness, - String nickname) { - this(opcode, result, sources, StdTypeList.EMPTY, branchingness, false, - nickname); - } - - /** - * Constructs a non-branching no-exception instance. The - * <code>branchingness</code> is always <code>BRANCH_NONE</code>, - * and it is never a call-like op (see {@link #isCallLike}). - * - * @param opcode the opcode; one of the constants in {@link RegOps} - * @param result non-null; result type of this operation; {@link - * Type#VOID} for no-result operations - * @param sources non-null; types of all the sources of this operation - * @param nickname null-ok; optional nickname (used for debugging) - */ - public Rop(int opcode, Type result, TypeList sources, String nickname) { - this(opcode, result, sources, StdTypeList.EMPTY, Rop.BRANCH_NONE, - false, nickname); - } - - /** - * Constructs a non-empty exceptions instance. Its - * <code>branchingness</code> is always <code>BRANCH_THROW</code>, - * but it is never a call-like op (see {@link #isCallLike}). - * - * @param opcode the opcode; one of the constants in {@link RegOps} - * @param result non-null; result type of this operation; {@link - * Type#VOID} for no-result operations - * @param sources non-null; types of all the sources of this operation - * @param exceptions non-null; list of possible types thrown by this - * operation - * @param nickname null-ok; optional nickname (used for debugging) - */ - public Rop(int opcode, Type result, TypeList sources, TypeList exceptions, - String nickname) { - this(opcode, result, sources, exceptions, Rop.BRANCH_THROW, false, - nickname); - } - - /** - * Constructs a non-nicknamed instance with non-empty exceptions, which - * is always a call-like op (see {@link #isCallLike}). Its - * <code>branchingness</code> is always <code>BRANCH_THROW</code>. - * - * @param opcode the opcode; one of the constants in {@link RegOps} - * @param sources non-null; types of all the sources of this operation - * @param exceptions non-null; list of possible types thrown by this - * operation - */ - public Rop(int opcode, TypeList sources, TypeList exceptions) { - this(opcode, Type.VOID, sources, exceptions, Rop.BRANCH_THROW, true, - null); - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - if (this == other) { - // Easy out. - return true; - } - - if (!(other instanceof Rop)) { - return false; - } - - Rop rop = (Rop) other; - - return (opcode == rop.opcode) && - (branchingness == rop.branchingness) && - (result == rop.result) && - sources.equals(rop.sources) && - exceptions.equals(rop.exceptions); - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - int h = (opcode * 31) + branchingness; - h = (h * 31) + result.hashCode(); - h = (h * 31) + sources.hashCode(); - h = (h * 31) + exceptions.hashCode(); - - return h; - } - - /** {@inheritDoc} */ - @Override - public String toString() { - StringBuffer sb = new StringBuffer(40); - - sb.append("Rop{"); - - sb.append(RegOps.opName(opcode)); - - if (result != Type.VOID) { - sb.append(" "); - sb.append(result); - } else { - sb.append(" ."); - } - - sb.append(" <-"); - - int sz = sources.size(); - if (sz == 0) { - sb.append(" ."); - } else { - for (int i = 0; i < sz; i++) { - sb.append(' '); - sb.append(sources.getType(i)); - } - } - - if (isCallLike) { - sb.append(" call"); - } - - sz = exceptions.size(); - if (sz != 0) { - sb.append(" throws"); - for (int i = 0; i < sz; i++) { - sb.append(' '); - Type one = exceptions.getType(i); - if (one == Type.THROWABLE) { - sb.append("<any>"); - } else { - sb.append(exceptions.getType(i)); - } - } - } else { - switch (branchingness) { - case BRANCH_NONE: sb.append(" flows"); break; - case BRANCH_RETURN: sb.append(" returns"); break; - case BRANCH_GOTO: sb.append(" gotos"); break; - case BRANCH_IF: sb.append(" ifs"); break; - case BRANCH_SWITCH: sb.append(" switches"); break; - default: sb.append(" " + Hex.u1(branchingness)); break; - } - } - - sb.append('}'); - - return sb.toString(); - } - - /** - * Gets the opcode. - * - * @return the opcode - */ - public int getOpcode() { - return opcode; - } - - /** - * Gets the result type. A return value of {@link Type#VOID} - * means this operation returns nothing. - * - * @return null-ok; the result spec - */ - public Type getResult() { - return result; - } - - /** - * Gets the source types. - * - * @return non-null; the source types - */ - public TypeList getSources() { - return sources; - } - - /** - * Gets the list of exception types that might be thrown. - * - * @return non-null; the list of exception types - */ - public TypeList getExceptions() { - return exceptions; - } - - /** - * Gets the branchingness of this instance. - * - * @return the branchingness - */ - public int getBranchingness() { - return branchingness; - } - - /** - * Gets whether this opcode is a function/method call or similar. - * - * @return <code>true</code> iff this opcode is call-like - */ - public boolean isCallLike() { - return isCallLike; - } - - - /** - * Gets whether this opcode is commutative (the order of its sources are - * unimportant) or not. All commutative Rops have exactly two sources and - * have no branchiness. - * - * @return true if rop is commutative - */ - public boolean isCommutative() { - switch (opcode) { - case RegOps.AND: - case RegOps.OR: - case RegOps.XOR: - case RegOps.ADD: - case RegOps.MUL: - return true; - default: - return false; - } - } - - /** - * Gets the nickname. If this instance has no nickname, this returns - * the result of calling {@link #toString}. - * - * @return non-null; the nickname - */ - public String getNickname() { - if (nickname != null) { - return nickname; - } - - return toString(); - } - - /** - * Gets whether this operation can possibly throw an exception. This - * is just a convenient wrapper for - * <code>getExceptions().size() != 0</code>. - * - * @return <code>true</code> iff this operation can possibly throw - */ - public final boolean canThrow() { - return (exceptions.size() != 0); - } -} diff --git a/dx/src/com/android/dx/rop/code/RopMethod.java b/dx/src/com/android/dx/rop/code/RopMethod.java deleted file mode 100644 index 0c0d8f1a7..000000000 --- a/dx/src/com/android/dx/rop/code/RopMethod.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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.util.Bits; -import com.android.dx.util.Hex; -import com.android.dx.util.IntList; - -/** - * All of the parts that make up a method at the rop layer. - */ -public final class RopMethod { - /** non-null; basic block list of the method */ - private final BasicBlockList blocks; - - /** >= 0; label for the block which starts the method */ - private final int firstLabel; - - /** - * null-ok; array of predecessors for each block, indexed by block - * label - */ - private IntList[] predecessors; - - /** - * null-ok; the predecessors for the implicit "exit" block, that is - * the labels for the blocks that return, if calculated - */ - private IntList exitPredecessors; - - /** - * Constructs an instance. - * - * @param blocks non-null; basic block list of the method - * @param firstLabel >= 0; the label of the first block to execute - */ - public RopMethod(BasicBlockList blocks, int firstLabel) { - if (blocks == null) { - throw new NullPointerException("blocks == null"); - } - - if (firstLabel < 0) { - throw new IllegalArgumentException("firstLabel < 0"); - } - - this.blocks = blocks; - this.firstLabel = firstLabel; - - this.predecessors = null; - this.exitPredecessors = null; - } - - /** - * Gets the basic block list for this method. - * - * @return non-null; the list - */ - public BasicBlockList getBlocks() { - return blocks; - } - - /** - * Gets the label for the first block in the method that this list - * represents. - * - * @return >= 0; the first-block label - */ - public int getFirstLabel() { - return firstLabel; - } - - /** - * Gets the predecessors associated with the given block. This throws - * an exception if there is no block with the given label. - * - * @param label >= 0; the label of the block in question - * @return non-null; the predecessors of that block - */ - public IntList labelToPredecessors(int label) { - if (exitPredecessors == null) { - calcPredecessors(); - } - - IntList result = predecessors[label]; - - if (result == null) { - throw new RuntimeException("no such block: " + Hex.u2(label)); - } - - return result; - } - - /** - * Gets the exit predecessors for this instance. - * - * @return non-null; the exit predecessors - */ - public IntList getExitPredecessors() { - if (exitPredecessors == null) { - calcPredecessors(); - } - - return exitPredecessors; - } - - - /** - * Returns an instance that is identical to this one, except that - * the registers in each instruction are offset by the given - * amount. - * - * @param delta the amount to offset register numbers by - * @return non-null; an appropriately-constructed instance - */ - public RopMethod withRegisterOffset(int delta) { - RopMethod result = new RopMethod(blocks.withRegisterOffset(delta), - firstLabel); - - if (exitPredecessors != null) { - /* - * The predecessors have been calculated. It's safe to - * inject these into the new instance, since the - * transformation being applied doesn't affect the - * predecessors. - */ - result.exitPredecessors = exitPredecessors; - result.predecessors = predecessors; - } - - return result; - } - - /** - * Calculates the predecessor sets for each block as well as for the - * exit. - */ - private void calcPredecessors() { - int maxLabel = blocks.getMaxLabel(); - IntList[] predecessors = new IntList[maxLabel]; - IntList exitPredecessors = new IntList(10); - int sz = blocks.size(); - - /* - * For each block, find its successors, and add the block's label to - * the successor's predecessors. - */ - for (int i = 0; i < sz; i++) { - BasicBlock one = blocks.get(i); - int label = one.getLabel(); - IntList successors = one.getSuccessors(); - int ssz = successors.size(); - if (ssz == 0) { - // This block exits. - exitPredecessors.add(label); - } else { - for (int j = 0; j < ssz; j++) { - int succLabel = successors.get(j); - IntList succPreds = predecessors[succLabel]; - if (succPreds == null) { - succPreds = new IntList(10); - predecessors[succLabel] = succPreds; - } - succPreds.add(label); - } - } - } - - // Sort and immutablize all the predecessor lists. - for (int i = 0; i < maxLabel; i++) { - IntList preds = predecessors[i]; - if (preds != null) { - preds.sort(); - preds.setImmutable(); - } - } - - exitPredecessors.sort(); - exitPredecessors.setImmutable(); - - /* - * The start label might not ever have had any predecessors - * added to it (probably doesn't, because of how Java gets - * translated into rop form). So, check for this and rectify - * the situation if required. - */ - if (predecessors[firstLabel] == null) { - predecessors[firstLabel] = IntList.EMPTY; - } - - this.predecessors = predecessors; - this.exitPredecessors = exitPredecessors; - } -} diff --git a/dx/src/com/android/dx/rop/code/Rops.java b/dx/src/com/android/dx/rop/code/Rops.java deleted file mode 100644 index b662656f7..000000000 --- a/dx/src/com/android/dx/rop/code/Rops.java +++ /dev/null @@ -1,2124 +0,0 @@ -/* - * 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.cst.Constant; -import com.android.dx.rop.cst.CstBaseMethodRef; -import com.android.dx.rop.cst.CstMethodRef; -import com.android.dx.rop.cst.CstType; -import com.android.dx.rop.type.Prototype; -import com.android.dx.rop.type.StdTypeList; -import com.android.dx.rop.type.Type; -import com.android.dx.rop.type.TypeBearer; -import com.android.dx.rop.type.TypeList; - -/** - * Standard instances of {@link Rop}. - */ -public final class Rops { - /** <code>nop()</code> */ - public static final Rop NOP = - new Rop(RegOps.NOP, Type.VOID, StdTypeList.EMPTY, "nop"); - - /** <code>r,x: int :: r = x;</code> */ - public static final Rop MOVE_INT = - new Rop(RegOps.MOVE, Type.INT, StdTypeList.INT, "move-int"); - - /** <code>r,x: long :: r = x;</code> */ - public static final Rop MOVE_LONG = - new Rop(RegOps.MOVE, Type.LONG, StdTypeList.LONG, "move-long"); - - /** <code>r,x: float :: r = x;</code> */ - public static final Rop MOVE_FLOAT = - new Rop(RegOps.MOVE, Type.FLOAT, StdTypeList.FLOAT, "move-float"); - - /** <code>r,x: double :: r = x;</code> */ - public static final Rop MOVE_DOUBLE = - new Rop(RegOps.MOVE, Type.DOUBLE, StdTypeList.DOUBLE, "move-double"); - - /** <code>r,x: Object :: r = x;</code> */ - public static final Rop MOVE_OBJECT = - new Rop(RegOps.MOVE, Type.OBJECT, StdTypeList.OBJECT, "move-object"); - - /** - * <code>r,x: ReturnAddress :: r = x;</code> - * - * Note that this rop-form instruction has no dex-form equivilent and - * must be removed before the dex conversion. - */ - public static final Rop MOVE_RETURN_ADDRESS = - new Rop(RegOps.MOVE, Type.RETURN_ADDRESS, - StdTypeList.RETURN_ADDRESS, "move-return-address"); - - /** <code>r,param(x): int :: r = param(x);</code> */ - public static final Rop MOVE_PARAM_INT = - new Rop(RegOps.MOVE_PARAM, Type.INT, StdTypeList.EMPTY, - "move-param-int"); - - /** <code>r,param(x): long :: r = param(x);</code> */ - public static final Rop MOVE_PARAM_LONG = - new Rop(RegOps.MOVE_PARAM, Type.LONG, StdTypeList.EMPTY, - "move-param-long"); - - /** <code>r,param(x): float :: r = param(x);</code> */ - public static final Rop MOVE_PARAM_FLOAT = - new Rop(RegOps.MOVE_PARAM, Type.FLOAT, StdTypeList.EMPTY, - "move-param-float"); - - /** <code>r,param(x): double :: r = param(x);</code> */ - public static final Rop MOVE_PARAM_DOUBLE = - new Rop(RegOps.MOVE_PARAM, Type.DOUBLE, StdTypeList.EMPTY, - "move-param-double"); - - /** <code>r,param(x): Object :: r = param(x);</code> */ - public static final Rop MOVE_PARAM_OBJECT = - new Rop(RegOps.MOVE_PARAM, Type.OBJECT, StdTypeList.EMPTY, - "move-param-object"); - - /** <code>r, literal: int :: r = literal;</code> */ - public static final Rop CONST_INT = - new Rop(RegOps.CONST, Type.INT, StdTypeList.EMPTY, "const-int"); - - /** <code>r, literal: long :: r = literal;</code> */ - public static final Rop CONST_LONG = - new Rop(RegOps.CONST, Type.LONG, StdTypeList.EMPTY, "const-long"); - - /** <code>r, literal: float :: r = literal;</code> */ - public static final Rop CONST_FLOAT = - new Rop(RegOps.CONST, Type.FLOAT, StdTypeList.EMPTY, "const-float"); - - /** <code>r, literal: double :: r = literal;</code> */ - public static final Rop CONST_DOUBLE = - new Rop(RegOps.CONST, Type.DOUBLE, StdTypeList.EMPTY, "const-double"); - - /** <code>r, literal: Object :: r = literal;</code> */ - public static final Rop CONST_OBJECT = - new Rop(RegOps.CONST, Type.OBJECT, StdTypeList.EMPTY, - Exceptions.LIST_Error, "const-object"); - - /** <code>r, literal: Object :: r = literal;</code> */ - public static final Rop CONST_OBJECT_NOTHROW = - new Rop(RegOps.CONST, Type.OBJECT, StdTypeList.EMPTY, - "const-object-nothrow"); - - /** <code>goto <i>label</i></code> */ - public static final Rop GOTO = - new Rop(RegOps.GOTO, Type.VOID, StdTypeList.EMPTY, Rop.BRANCH_GOTO, - "goto"); - - /** <code>x: int :: if (x == 0) goto <i>label</i></code> */ - public static final Rop IF_EQZ_INT = - new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF, - "if-eqz-int"); - - /** <code>x: int :: if (x != 0) goto <i>label</i></code> */ - public static final Rop IF_NEZ_INT = - new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF, - "if-nez-int"); - - /** <code>x: int :: if (x < 0) goto <i>label</i></code> */ - public static final Rop IF_LTZ_INT = - new Rop(RegOps.IF_LT, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF, - "if-ltz-int"); - - /** <code>x: int :: if (x >= 0) goto <i>label</i></code> */ - public static final Rop IF_GEZ_INT = - new Rop(RegOps.IF_GE, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF, - "if-gez-int"); - - /** <code>x: int :: if (x <= 0) goto <i>label</i></code> */ - public static final Rop IF_LEZ_INT = - new Rop(RegOps.IF_LE, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF, - "if-lez-int"); - - /** <code>x: int :: if (x > 0) goto <i>label</i></code> */ - public static final Rop IF_GTZ_INT = - new Rop(RegOps.IF_GT, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF, - "if-gtz-int"); - - /** <code>x: Object :: if (x == null) goto <i>label</i></code> */ - public static final Rop IF_EQZ_OBJECT = - new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.OBJECT, Rop.BRANCH_IF, - "if-eqz-object"); - - /** <code>x: Object :: if (x != null) goto <i>label</i></code> */ - public static final Rop IF_NEZ_OBJECT = - new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.OBJECT, Rop.BRANCH_IF, - "if-nez-object"); - - /** <code>x,y: int :: if (x == y) goto <i>label</i></code> */ - public static final Rop IF_EQ_INT = - new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF, - "if-eq-int"); - - /** <code>x,y: int :: if (x != y) goto <i>label</i></code> */ - public static final Rop IF_NE_INT = - new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF, - "if-ne-int"); - - /** <code>x,y: int :: if (x < y) goto <i>label</i></code> */ - public static final Rop IF_LT_INT = - new Rop(RegOps.IF_LT, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF, - "if-lt-int"); - - /** <code>x,y: int :: if (x >= y) goto <i>label</i></code> */ - public static final Rop IF_GE_INT = - new Rop(RegOps.IF_GE, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF, - "if-ge-int"); - - /** <code>x,y: int :: if (x <= y) goto <i>label</i></code> */ - public static final Rop IF_LE_INT = - new Rop(RegOps.IF_LE, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF, - "if-le-int"); - - /** <code>x,y: int :: if (x > y) goto <i>label</i></code> */ - public static final Rop IF_GT_INT = - new Rop(RegOps.IF_GT, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF, - "if-gt-int"); - - /** <code>x,y: Object :: if (x == y) goto <i>label</i></code> */ - public static final Rop IF_EQ_OBJECT = - new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.OBJECT_OBJECT, - Rop.BRANCH_IF, "if-eq-object"); - - /** <code>x,y: Object :: if (x != y) goto <i>label</i></code> */ - public static final Rop IF_NE_OBJECT = - new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.OBJECT_OBJECT, - Rop.BRANCH_IF, "if-ne-object"); - - /** <code>x: int :: goto switchtable[x]</code> */ - public static final Rop SWITCH = - new Rop(RegOps.SWITCH, Type.VOID, StdTypeList.INT, Rop.BRANCH_SWITCH, - "switch"); - - /** <code>r,x,y: int :: r = x + y;</code> */ - public static final Rop ADD_INT = - new Rop(RegOps.ADD, Type.INT, StdTypeList.INT_INT, "add-int"); - - /** <code>r,x,y: long :: r = x + y;</code> */ - public static final Rop ADD_LONG = - new Rop(RegOps.ADD, Type.LONG, StdTypeList.LONG_LONG, "add-long"); - - /** <code>r,x,y: float :: r = x + y;</code> */ - public static final Rop ADD_FLOAT = - new Rop(RegOps.ADD, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "add-float"); - - /** <code>r,x,y: double :: r = x + y;</code> */ - public static final Rop ADD_DOUBLE = - new Rop(RegOps.ADD, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE, - Rop.BRANCH_NONE, "add-double"); - - /** <code>r,x,y: int :: r = x - y;</code> */ - public static final Rop SUB_INT = - new Rop(RegOps.SUB, Type.INT, StdTypeList.INT_INT, "sub-int"); - - /** <code>r,x,y: long :: r = x - y;</code> */ - public static final Rop SUB_LONG = - new Rop(RegOps.SUB, Type.LONG, StdTypeList.LONG_LONG, "sub-long"); - - /** <code>r,x,y: float :: r = x - y;</code> */ - public static final Rop SUB_FLOAT = - new Rop(RegOps.SUB, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "sub-float"); - - /** <code>r,x,y: double :: r = x - y;</code> */ - public static final Rop SUB_DOUBLE = - new Rop(RegOps.SUB, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE, - Rop.BRANCH_NONE, "sub-double"); - - /** <code>r,x,y: int :: r = x * y;</code> */ - public static final Rop MUL_INT = - new Rop(RegOps.MUL, Type.INT, StdTypeList.INT_INT, "mul-int"); - - /** <code>r,x,y: long :: r = x * y;</code> */ - public static final Rop MUL_LONG = - new Rop(RegOps.MUL, Type.LONG, StdTypeList.LONG_LONG, "mul-long"); - - /** <code>r,x,y: float :: r = x * y;</code> */ - public static final Rop MUL_FLOAT = - new Rop(RegOps.MUL, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "mul-float"); - - /** <code>r,x,y: double :: r = x * y;</code> */ - public static final Rop MUL_DOUBLE = - new Rop(RegOps.MUL, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE, - Rop.BRANCH_NONE, "mul-double"); - - /** <code>r,x,y: int :: r = x / y;</code> */ - public static final Rop DIV_INT = - new Rop(RegOps.DIV, Type.INT, StdTypeList.INT_INT, - Exceptions.LIST_Error_ArithmeticException, "div-int"); - - /** <code>r,x,y: long :: r = x / y;</code> */ - public static final Rop DIV_LONG = - new Rop(RegOps.DIV, Type.LONG, StdTypeList.LONG_LONG, - Exceptions.LIST_Error_ArithmeticException, "div-long"); - - /** <code>r,x,y: float :: r = x / y;</code> */ - public static final Rop DIV_FLOAT = - new Rop(RegOps.DIV, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "div-float"); - - /** <code>r,x,y: double :: r = x / y;</code> */ - public static final Rop DIV_DOUBLE = - new Rop(RegOps.DIV, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE, - "div-double"); - - /** <code>r,x,y: int :: r = x % y;</code> */ - public static final Rop REM_INT = - new Rop(RegOps.REM, Type.INT, StdTypeList.INT_INT, - Exceptions.LIST_Error_ArithmeticException, "rem-int"); - - /** <code>r,x,y: long :: r = x % y;</code> */ - public static final Rop REM_LONG = - new Rop(RegOps.REM, Type.LONG, StdTypeList.LONG_LONG, - Exceptions.LIST_Error_ArithmeticException, "rem-long"); - - /** <code>r,x,y: float :: r = x % y;</code> */ - public static final Rop REM_FLOAT = - new Rop(RegOps.REM, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "rem-float"); - - /** <code>r,x,y: double :: r = x % y;</code> */ - public static final Rop REM_DOUBLE = - new Rop(RegOps.REM, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE, - "rem-double"); - - /** <code>r,x: int :: r = -x;</code> */ - public static final Rop NEG_INT = - new Rop(RegOps.NEG, Type.INT, StdTypeList.INT, "neg-int"); - - /** <code>r,x: long :: r = -x;</code> */ - public static final Rop NEG_LONG = - new Rop(RegOps.NEG, Type.LONG, StdTypeList.LONG, "neg-long"); - - /** <code>r,x: float :: r = -x;</code> */ - public static final Rop NEG_FLOAT = - new Rop(RegOps.NEG, Type.FLOAT, StdTypeList.FLOAT, "neg-float"); - - /** <code>r,x: double :: r = -x;</code> */ - public static final Rop NEG_DOUBLE = - new Rop(RegOps.NEG, Type.DOUBLE, StdTypeList.DOUBLE, "neg-double"); - - /** <code>r,x,y: int :: r = x & y;</code> */ - public static final Rop AND_INT = - new Rop(RegOps.AND, Type.INT, StdTypeList.INT_INT, "and-int"); - - /** <code>r,x,y: long :: r = x & y;</code> */ - public static final Rop AND_LONG = - new Rop(RegOps.AND, Type.LONG, StdTypeList.LONG_LONG, "and-long"); - - /** <code>r,x,y: int :: r = x | y;</code> */ - public static final Rop OR_INT = - new Rop(RegOps.OR, Type.INT, StdTypeList.INT_INT, "or-int"); - - /** <code>r,x,y: long :: r = x | y;</code> */ - public static final Rop OR_LONG = - new Rop(RegOps.OR, Type.LONG, StdTypeList.LONG_LONG, "or-long"); - - /** <code>r,x,y: int :: r = x ^ y;</code> */ - public static final Rop XOR_INT = - new Rop(RegOps.XOR, Type.INT, StdTypeList.INT_INT, "xor-int"); - - /** <code>r,x,y: long :: r = x ^ y;</code> */ - public static final Rop XOR_LONG = - new Rop(RegOps.XOR, Type.LONG, StdTypeList.LONG_LONG, "xor-long"); - - /** <code>r,x,y: int :: r = x << y;</code> */ - public static final Rop SHL_INT = - new Rop(RegOps.SHL, Type.INT, StdTypeList.INT_INT, "shl-int"); - - /** <code>r,x: long; y: int :: r = x << y;</code> */ - public static final Rop SHL_LONG = - new Rop(RegOps.SHL, Type.LONG, StdTypeList.LONG_INT, "shl-long"); - - /** <code>r,x,y: int :: r = x >> y;</code> */ - public static final Rop SHR_INT = - new Rop(RegOps.SHR, Type.INT, StdTypeList.INT_INT, "shr-int"); - - /** <code>r,x: long; y: int :: r = x >> y;</code> */ - public static final Rop SHR_LONG = - new Rop(RegOps.SHR, Type.LONG, StdTypeList.LONG_INT, "shr-long"); - - /** <code>r,x,y: int :: r = x >>> y;</code> */ - public static final Rop USHR_INT = - new Rop(RegOps.USHR, Type.INT, StdTypeList.INT_INT, "ushr-int"); - - /** <code>r,x: long; y: int :: r = x >>> y;</code> */ - public static final Rop USHR_LONG = - new Rop(RegOps.USHR, Type.LONG, StdTypeList.LONG_INT, "ushr-long"); - - /** <code>r,x: int :: r = ~x;</code> */ - public static final Rop NOT_INT = - new Rop(RegOps.NOT, Type.INT, StdTypeList.INT, "not-int"); - - /** <code>r,x: long :: r = ~x;</code> */ - public static final Rop NOT_LONG = - new Rop(RegOps.NOT, Type.LONG, StdTypeList.LONG, "not-long"); - - /** <code>r,x,c: int :: r = x + c;</code> */ - public static final Rop ADD_CONST_INT = - new Rop(RegOps.ADD, Type.INT, StdTypeList.INT, "add-const-int"); - - /** <code>r,x,c: long :: r = x + c;</code> */ - public static final Rop ADD_CONST_LONG = - new Rop(RegOps.ADD, Type.LONG, StdTypeList.LONG, "add-const-long"); - - /** <code>r,x,c: float :: r = x + c;</code> */ - public static final Rop ADD_CONST_FLOAT = - new Rop(RegOps.ADD, Type.FLOAT, StdTypeList.FLOAT, "add-const-float"); - - /** <code>r,x,c: double :: r = x + c;</code> */ - public static final Rop ADD_CONST_DOUBLE = - new Rop(RegOps.ADD, Type.DOUBLE, StdTypeList.DOUBLE, - "add-const-double"); - - /** <code>r,x,c: int :: r = x - c;</code> */ - public static final Rop SUB_CONST_INT = - new Rop(RegOps.SUB, Type.INT, StdTypeList.INT, "sub-const-int"); - - /** <code>r,x,c: long :: r = x - c;</code> */ - public static final Rop SUB_CONST_LONG = - new Rop(RegOps.SUB, Type.LONG, StdTypeList.LONG, "sub-const-long"); - - /** <code>r,x,c: float :: r = x - c;</code> */ - public static final Rop SUB_CONST_FLOAT = - new Rop(RegOps.SUB, Type.FLOAT, StdTypeList.FLOAT, "sub-const-float"); - - /** <code>r,x,c: double :: r = x - c;</code> */ - public static final Rop SUB_CONST_DOUBLE = - new Rop(RegOps.SUB, Type.DOUBLE, StdTypeList.DOUBLE, - "sub-const-double"); - - /** <code>r,x,c: int :: r = x * c;</code> */ - public static final Rop MUL_CONST_INT = - new Rop(RegOps.MUL, Type.INT, StdTypeList.INT, "mul-const-int"); - - /** <code>r,x,c: long :: r = x * c;</code> */ - public static final Rop MUL_CONST_LONG = - new Rop(RegOps.MUL, Type.LONG, StdTypeList.LONG, "mul-const-long"); - - /** <code>r,x,c: float :: r = x * c;</code> */ - public static final Rop MUL_CONST_FLOAT = - new Rop(RegOps.MUL, Type.FLOAT, StdTypeList.FLOAT, "mul-const-float"); - - /** <code>r,x,c: double :: r = x * c;</code> */ - public static final Rop MUL_CONST_DOUBLE = - new Rop(RegOps.MUL, Type.DOUBLE, StdTypeList.DOUBLE, - "mul-const-double"); - - /** <code>r,x,c: int :: r = x / c;</code> */ - public static final Rop DIV_CONST_INT = - new Rop(RegOps.DIV, Type.INT, StdTypeList.INT, - Exceptions.LIST_Error_ArithmeticException, "div-const-int"); - - /** <code>r,x,c: long :: r = x / c;</code> */ - public static final Rop DIV_CONST_LONG = - new Rop(RegOps.DIV, Type.LONG, StdTypeList.LONG, - Exceptions.LIST_Error_ArithmeticException, "div-const-long"); - - /** <code>r,x,c: float :: r = x / c;</code> */ - public static final Rop DIV_CONST_FLOAT = - new Rop(RegOps.DIV, Type.FLOAT, StdTypeList.FLOAT, "div-const-float"); - - /** <code>r,x,c: double :: r = x / c;</code> */ - public static final Rop DIV_CONST_DOUBLE = - new Rop(RegOps.DIV, Type.DOUBLE, StdTypeList.DOUBLE, - "div-const-double"); - - /** <code>r,x,c: int :: r = x % c;</code> */ - public static final Rop REM_CONST_INT = - new Rop(RegOps.REM, Type.INT, StdTypeList.INT, - Exceptions.LIST_Error_ArithmeticException, "rem-const-int"); - - /** <code>r,x,c: long :: r = x % c;</code> */ - public static final Rop REM_CONST_LONG = - new Rop(RegOps.REM, Type.LONG, StdTypeList.LONG, - Exceptions.LIST_Error_ArithmeticException, "rem-const-long"); - - /** <code>r,x,c: float :: r = x % c;</code> */ - public static final Rop REM_CONST_FLOAT = - new Rop(RegOps.REM, Type.FLOAT, StdTypeList.FLOAT, "rem-const-float"); - - /** <code>r,x,c: double :: r = x % c;</code> */ - public static final Rop REM_CONST_DOUBLE = - new Rop(RegOps.REM, Type.DOUBLE, StdTypeList.DOUBLE, - "rem-const-double"); - - /** <code>r,x,c: int :: r = x & c;</code> */ - public static final Rop AND_CONST_INT = - new Rop(RegOps.AND, Type.INT, StdTypeList.INT, "and-const-int"); - - /** <code>r,x,c: long :: r = x & c;</code> */ - public static final Rop AND_CONST_LONG = - new Rop(RegOps.AND, Type.LONG, StdTypeList.LONG, "and-const-long"); - - /** <code>r,x,c: int :: r = x | c;</code> */ - public static final Rop OR_CONST_INT = - new Rop(RegOps.OR, Type.INT, StdTypeList.INT, "or-const-int"); - - /** <code>r,x,c: long :: r = x | c;</code> */ - public static final Rop OR_CONST_LONG = - new Rop(RegOps.OR, Type.LONG, StdTypeList.LONG, "or-const-long"); - - /** <code>r,x,c: int :: r = x ^ c;</code> */ - public static final Rop XOR_CONST_INT = - new Rop(RegOps.XOR, Type.INT, StdTypeList.INT, "xor-const-int"); - - /** <code>r,x,c: long :: r = x ^ c;</code> */ - public static final Rop XOR_CONST_LONG = - new Rop(RegOps.XOR, Type.LONG, StdTypeList.LONG, "xor-const-long"); - - /** <code>r,x,c: int :: r = x << c;</code> */ - public static final Rop SHL_CONST_INT = - new Rop(RegOps.SHL, Type.INT, StdTypeList.INT, "shl-const-int"); - - /** <code>r,x: long; c: int :: r = x << c;</code> */ - public static final Rop SHL_CONST_LONG = - new Rop(RegOps.SHL, Type.LONG, StdTypeList.INT, "shl-const-long"); - - /** <code>r,x,c: int :: r = x >> c;</code> */ - public static final Rop SHR_CONST_INT = - new Rop(RegOps.SHR, Type.INT, StdTypeList.INT, "shr-const-int"); - - /** <code>r,x: long; c: int :: r = x >> c;</code> */ - public static final Rop SHR_CONST_LONG = - new Rop(RegOps.SHR, Type.LONG, StdTypeList.INT, "shr-const-long"); - - /** <code>r,x,c: int :: r = x >>> c;</code> */ - public static final Rop USHR_CONST_INT = - new Rop(RegOps.USHR, Type.INT, StdTypeList.INT, "ushr-const-int"); - - /** <code>r,x: long; c: int :: r = x >>> c;</code> */ - public static final Rop USHR_CONST_LONG = - new Rop(RegOps.USHR, Type.LONG, StdTypeList.INT, "ushr-const-long"); - - /** <code>r: int; x,y: long :: r = cmp(x, y);</code> */ - public static final Rop CMPL_LONG = - new Rop(RegOps.CMPL, Type.INT, StdTypeList.LONG_LONG, "cmpl-long"); - - /** <code>r: int; x,y: float :: r = cmpl(x, y);</code> */ - public static final Rop CMPL_FLOAT = - new Rop(RegOps.CMPL, Type.INT, StdTypeList.FLOAT_FLOAT, "cmpl-float"); - - /** <code>r: int; x,y: double :: r = cmpl(x, y);</code> */ - public static final Rop CMPL_DOUBLE = - new Rop(RegOps.CMPL, Type.INT, StdTypeList.DOUBLE_DOUBLE, - "cmpl-double"); - - /** <code>r: int; x,y: float :: r = cmpg(x, y);</code> */ - public static final Rop CMPG_FLOAT = - new Rop(RegOps.CMPG, Type.INT, StdTypeList.FLOAT_FLOAT, "cmpg-float"); - - /** <code>r: int; x,y: double :: r = cmpg(x, y);</code> */ - public static final Rop CMPG_DOUBLE = - new Rop(RegOps.CMPG, Type.INT, StdTypeList.DOUBLE_DOUBLE, - "cmpg-double"); - - /** <code>r: int; x: long :: r = (int) x</code> */ - public static final Rop CONV_L2I = - new Rop(RegOps.CONV, Type.INT, StdTypeList.LONG, "conv-l2i"); - - /** <code>r: int; x: float :: r = (int) x</code> */ - public static final Rop CONV_F2I = - new Rop(RegOps.CONV, Type.INT, StdTypeList.FLOAT, "conv-f2i"); - - /** <code>r: int; x: double :: r = (int) x</code> */ - public static final Rop CONV_D2I = - new Rop(RegOps.CONV, Type.INT, StdTypeList.DOUBLE, "conv-d2i"); - - /** <code>r: long; x: int :: r = (long) x</code> */ - public static final Rop CONV_I2L = - new Rop(RegOps.CONV, Type.LONG, StdTypeList.INT, "conv-i2l"); - - /** <code>r: long; x: float :: r = (long) x</code> */ - public static final Rop CONV_F2L = - new Rop(RegOps.CONV, Type.LONG, StdTypeList.FLOAT, "conv-f2l"); - - /** <code>r: long; x: double :: r = (long) x</code> */ - public static final Rop CONV_D2L = - new Rop(RegOps.CONV, Type.LONG, StdTypeList.DOUBLE, "conv-d2l"); - - /** <code>r: float; x: int :: r = (float) x</code> */ - public static final Rop CONV_I2F = - new Rop(RegOps.CONV, Type.FLOAT, StdTypeList.INT, "conv-i2f"); - - /** <code>r: float; x: long :: r = (float) x</code> */ - public static final Rop CONV_L2F = - new Rop(RegOps.CONV, Type.FLOAT, StdTypeList.LONG, "conv-l2f"); - - /** <code>r: float; x: double :: r = (float) x</code> */ - public static final Rop CONV_D2F = - new Rop(RegOps.CONV, Type.FLOAT, StdTypeList.DOUBLE, "conv-d2f"); - - /** <code>r: double; x: int :: r = (double) x</code> */ - public static final Rop CONV_I2D = - new Rop(RegOps.CONV, Type.DOUBLE, StdTypeList.INT, "conv-i2d"); - - /** <code>r: double; x: long :: r = (double) x</code> */ - public static final Rop CONV_L2D = - new Rop(RegOps.CONV, Type.DOUBLE, StdTypeList.LONG, "conv-l2d"); - - /** <code>r: double; x: float :: r = (double) x</code> */ - public static final Rop CONV_F2D = - new Rop(RegOps.CONV, Type.DOUBLE, StdTypeList.FLOAT, "conv-f2d"); - - /** - * <code>r,x: int :: r = (x << 24) >> 24</code> (Java-style - * convert int to byte) - */ - public static final Rop TO_BYTE = - new Rop(RegOps.TO_BYTE, Type.INT, StdTypeList.INT, "to-byte"); - - /** - * <code>r,x: int :: r = x & 0xffff</code> (Java-style - * convert int to char) - */ - public static final Rop TO_CHAR = - new Rop(RegOps.TO_CHAR, Type.INT, StdTypeList.INT, "to-char"); - - /** - * <code>r,x: int :: r = (x << 16) >> 16</code> (Java-style - * convert int to short) - */ - public static final Rop TO_SHORT = - new Rop(RegOps.TO_SHORT, Type.INT, StdTypeList.INT, "to-short"); - - /** <code>return void</code> */ - public static final Rop RETURN_VOID = - new Rop(RegOps.RETURN, Type.VOID, StdTypeList.EMPTY, Rop.BRANCH_RETURN, - "return-void"); - - /** <code>x: int; return x</code> */ - public static final Rop RETURN_INT = - new Rop(RegOps.RETURN, Type.VOID, StdTypeList.INT, Rop.BRANCH_RETURN, - "return-int"); - - /** <code>x: long; return x</code> */ - public static final Rop RETURN_LONG = - new Rop(RegOps.RETURN, Type.VOID, StdTypeList.LONG, Rop.BRANCH_RETURN, - "return-long"); - - /** <code>x: float; return x</code> */ - public static final Rop RETURN_FLOAT = - new Rop(RegOps.RETURN, Type.VOID, StdTypeList.FLOAT, Rop.BRANCH_RETURN, - "return-float"); - - /** <code>x: double; return x</code> */ - public static final Rop RETURN_DOUBLE = - new Rop(RegOps.RETURN, Type.VOID, StdTypeList.DOUBLE, - Rop.BRANCH_RETURN, "return-double"); - - /** <code>x: Object; return x</code> */ - public static final Rop RETURN_OBJECT = - new Rop(RegOps.RETURN, Type.VOID, StdTypeList.OBJECT, - Rop.BRANCH_RETURN, "return-object"); - - /** <code>T: any type; r: int; x: T[]; :: r = x.length</code> */ - public static final Rop ARRAY_LENGTH = - new Rop(RegOps.ARRAY_LENGTH, Type.INT, StdTypeList.OBJECT, - Exceptions.LIST_Error_NullPointerException, "array-length"); - - /** <code>x: Throwable :: throw(x)</code> */ - public static final Rop THROW = - new Rop(RegOps.THROW, Type.VOID, StdTypeList.THROWABLE, - StdTypeList.THROWABLE, "throw"); - - /** <code>x: Object :: monitorenter(x)</code> */ - public static final Rop MONITOR_ENTER = - new Rop(RegOps.MONITOR_ENTER, Type.VOID, StdTypeList.OBJECT, - Exceptions.LIST_Error_NullPointerException, "monitor-enter"); - - /** <code>x: Object :: monitorexit(x)</code> */ - public static final Rop MONITOR_EXIT = - new Rop(RegOps.MONITOR_EXIT, Type.VOID, StdTypeList.OBJECT, - Exceptions.LIST_Error_Null_IllegalMonitorStateException, - "monitor-exit"); - - /** <code>r,y: int; x: int[] :: r = x[y]</code> */ - public static final Rop AGET_INT = - new Rop(RegOps.AGET, Type.INT, StdTypeList.INTARR_INT, - Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, - "aget-int"); - - /** <code>r: long; x: long[]; y: int :: r = x[y]</code> */ - public static final Rop AGET_LONG = - new Rop(RegOps.AGET, Type.LONG, StdTypeList.LONGARR_INT, - Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, - "aget-long"); - - /** <code>r: float; x: float[]; y: int :: r = x[y]</code> */ - public static final Rop AGET_FLOAT = - new Rop(RegOps.AGET, Type.FLOAT, StdTypeList.FLOATARR_INT, - Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, - "aget-float"); - - /** <code>r: double; x: double[]; y: int :: r = x[y]</code> */ - public static final Rop AGET_DOUBLE = - new Rop(RegOps.AGET, Type.DOUBLE, StdTypeList.DOUBLEARR_INT, - Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, - "aget-double"); - - /** <code>r: Object; x: Object[]; y: int :: r = x[y]</code> */ - public static final Rop AGET_OBJECT = - new Rop(RegOps.AGET, Type.OBJECT, StdTypeList.OBJECTARR_INT, - Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, - "aget-object"); - - /** <code>r: boolean; x: boolean[]; y: int :: r = x[y]</code> */ - public static final Rop AGET_BOOLEAN = - new Rop(RegOps.AGET, Type.INT, StdTypeList.BOOLEANARR_INT, - Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, - "aget-boolean"); - - /** <code>r: byte; x: byte[]; y: int :: r = x[y]</code> */ - public static final Rop AGET_BYTE = - new Rop(RegOps.AGET, Type.INT, StdTypeList.BYTEARR_INT, - Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aget-byte"); - - /** <code>r: char; x: char[]; y: int :: r = x[y]</code> */ - public static final Rop AGET_CHAR = - new Rop(RegOps.AGET, Type.INT, StdTypeList.CHARARR_INT, - Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aget-char"); - - /** <code>r: short; x: short[]; y: int :: r = x[y]</code> */ - public static final Rop AGET_SHORT = - new Rop(RegOps.AGET, Type.INT, StdTypeList.SHORTARR_INT, - Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, - "aget-short"); - - /** <code>x,z: int; y: int[] :: y[z] = x</code> */ - public static final Rop APUT_INT = - new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_INTARR_INT, - Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aput-int"); - - /** <code>x: long; y: long[]; z: int :: y[z] = x</code> */ - public static final Rop APUT_LONG = - new Rop(RegOps.APUT, Type.VOID, StdTypeList.LONG_LONGARR_INT, - Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aput-long"); - - /** <code>x: float; y: float[]; z: int :: y[z] = x</code> */ - public static final Rop APUT_FLOAT = - new Rop(RegOps.APUT, Type.VOID, StdTypeList.FLOAT_FLOATARR_INT, - Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, - "aput-float"); - - /** <code>x: double; y: double[]; z: int :: y[z] = x</code> */ - public static final Rop APUT_DOUBLE = - new Rop(RegOps.APUT, Type.VOID, StdTypeList.DOUBLE_DOUBLEARR_INT, - Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, - "aput-double"); - - /** <code>x: Object; y: Object[]; z: int :: y[z] = x</code> */ - public static final Rop APUT_OBJECT = - new Rop(RegOps.APUT, Type.VOID, StdTypeList.OBJECT_OBJECTARR_INT, - Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore, - "aput-object"); - - /** <code>x: boolean; y: boolean[]; z: int :: y[z] = x</code> */ - public static final Rop APUT_BOOLEAN = - new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_BOOLEANARR_INT, - Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore, - "aput-boolean"); - - /** <code>x: byte; y: byte[]; z: int :: y[z] = x</code> */ - public static final Rop APUT_BYTE = - new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_BYTEARR_INT, - Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore, "aput-byte"); - - /** <code>x: char; y: char[]; z: int :: y[z] = x</code> */ - public static final Rop APUT_CHAR = - new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_CHARARR_INT, - Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore, "aput-char"); - - /** <code>x: short; y: short[]; z: int :: y[z] = x</code> */ - public static final Rop APUT_SHORT = - new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_SHORTARR_INT, - Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore, - "aput-short"); - - /** - * <code>T: any non-array object type :: r = - * alloc(T)</code> (allocate heap space for an object) - */ - public static final Rop NEW_INSTANCE = - new Rop(RegOps.NEW_INSTANCE, Type.OBJECT, StdTypeList.EMPTY, - Exceptions.LIST_Error, "new-instance"); - - /** <code>r: int[]; x: int :: r = new int[x]</code> */ - public static final Rop NEW_ARRAY_INT = - new Rop(RegOps.NEW_ARRAY, Type.INT_ARRAY, StdTypeList.INT, - Exceptions.LIST_Error_NegativeArraySizeException, - "new-array-int"); - - /** <code>r: long[]; x: int :: r = new long[x]</code> */ - public static final Rop NEW_ARRAY_LONG = - new Rop(RegOps.NEW_ARRAY, Type.LONG_ARRAY, StdTypeList.INT, - Exceptions.LIST_Error_NegativeArraySizeException, - "new-array-long"); - - /** <code>r: float[]; x: int :: r = new float[x]</code> */ - public static final Rop NEW_ARRAY_FLOAT = - new Rop(RegOps.NEW_ARRAY, Type.FLOAT_ARRAY, StdTypeList.INT, - Exceptions.LIST_Error_NegativeArraySizeException, - "new-array-float"); - - /** <code>r: double[]; x: int :: r = new double[x]</code> */ - public static final Rop NEW_ARRAY_DOUBLE = - new Rop(RegOps.NEW_ARRAY, Type.DOUBLE_ARRAY, StdTypeList.INT, - Exceptions.LIST_Error_NegativeArraySizeException, - "new-array-double"); - - /** <code>r: boolean[]; x: int :: r = new boolean[x]</code> */ - public static final Rop NEW_ARRAY_BOOLEAN = - new Rop(RegOps.NEW_ARRAY, Type.BOOLEAN_ARRAY, StdTypeList.INT, - Exceptions.LIST_Error_NegativeArraySizeException, - "new-array-boolean"); - - /** <code>r: byte[]; x: int :: r = new byte[x]</code> */ - public static final Rop NEW_ARRAY_BYTE = - new Rop(RegOps.NEW_ARRAY, Type.BYTE_ARRAY, StdTypeList.INT, - Exceptions.LIST_Error_NegativeArraySizeException, - "new-array-byte"); - - /** <code>r: char[]; x: int :: r = new char[x]</code> */ - public static final Rop NEW_ARRAY_CHAR = - new Rop(RegOps.NEW_ARRAY, Type.CHAR_ARRAY, StdTypeList.INT, - Exceptions.LIST_Error_NegativeArraySizeException, - "new-array-char"); - - /** <code>r: short[]; x: int :: r = new short[x]</code> */ - public static final Rop NEW_ARRAY_SHORT = - new Rop(RegOps.NEW_ARRAY, Type.SHORT_ARRAY, StdTypeList.INT, - Exceptions.LIST_Error_NegativeArraySizeException, - "new-array-short"); - - /** - * <code>T: any non-array object type; x: Object :: (T) x</code> (can - * throw <code>ClassCastException</code>) - */ - public static final Rop CHECK_CAST = - new Rop(RegOps.CHECK_CAST, Type.VOID, StdTypeList.OBJECT, - Exceptions.LIST_Error_ClassCastException, "check-cast"); - - /** - * <code>T: any non-array object type; x: Object :: x instanceof - * T</code>. Note: This is listed as throwing <code>Error</code> - * explicitly because the op <i>can</i> throw, but there are no - * other predefined exceptions for it. - */ - public static final Rop INSTANCE_OF = - new Rop(RegOps.INSTANCE_OF, Type.INT, StdTypeList.OBJECT, - Exceptions.LIST_Error, "instance-of"); - - /** - * <code>r: int; x: Object; f: instance field spec of - * type int :: r = x.f</code> - */ - public static final Rop GET_FIELD_INT = - new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT, - Exceptions.LIST_Error_NullPointerException, "get-field-int"); - - /** - * <code>r: long; x: Object; f: instance field spec of - * type long :: r = x.f</code> - */ - public static final Rop GET_FIELD_LONG = - new Rop(RegOps.GET_FIELD, Type.LONG, StdTypeList.OBJECT, - Exceptions.LIST_Error_NullPointerException, "get-field-long"); - - /** - * <code>r: float; x: Object; f: instance field spec of - * type float :: r = x.f</code> - */ - public static final Rop GET_FIELD_FLOAT = - new Rop(RegOps.GET_FIELD, Type.FLOAT, StdTypeList.OBJECT, - Exceptions.LIST_Error_NullPointerException, - "get-field-float"); - - /** - * <code>r: double; x: Object; f: instance field spec of - * type double :: r = x.f</code> - */ - public static final Rop GET_FIELD_DOUBLE = - new Rop(RegOps.GET_FIELD, Type.DOUBLE, StdTypeList.OBJECT, - Exceptions.LIST_Error_NullPointerException, - "get-field-double"); - - /** - * <code>r: Object; x: Object; f: instance field spec of - * type Object :: r = x.f</code> - */ - public static final Rop GET_FIELD_OBJECT = - new Rop(RegOps.GET_FIELD, Type.OBJECT, StdTypeList.OBJECT, - Exceptions.LIST_Error_NullPointerException, - "get-field-object"); - - /** - * <code>r: boolean; x: Object; f: instance field spec of - * type boolean :: r = x.f</code> - */ - public static final Rop GET_FIELD_BOOLEAN = - new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT, - Exceptions.LIST_Error_NullPointerException, - "get-field-boolean"); - - /** - * <code>r: byte; x: Object; f: instance field spec of - * type byte :: r = x.f</code> - */ - public static final Rop GET_FIELD_BYTE = - new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT, - Exceptions.LIST_Error_NullPointerException, - "get-field-byte"); - - /** - * <code>r: char; x: Object; f: instance field spec of - * type char :: r = x.f</code> - */ - public static final Rop GET_FIELD_CHAR = - new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT, - Exceptions.LIST_Error_NullPointerException, - "get-field-char"); - - /** - * <code>r: short; x: Object; f: instance field spec of - * type short :: r = x.f</code> - */ - public static final Rop GET_FIELD_SHORT = - new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT, - Exceptions.LIST_Error_NullPointerException, - "get-field-short"); - - /** - * <code>r: int; f: static field spec of type int :: r = - * f</code> - */ - public static final Rop GET_STATIC_INT = - new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY, - Exceptions.LIST_Error, "get-static-int"); - - /** - * <code>r: long; f: static field spec of type long :: r = - * f</code> - */ - public static final Rop GET_STATIC_LONG = - new Rop(RegOps.GET_STATIC, Type.LONG, StdTypeList.EMPTY, - Exceptions.LIST_Error, "get-static-long"); - - /** - * <code>r: float; f: static field spec of type float :: r = - * f</code> - */ - public static final Rop GET_STATIC_FLOAT = - new Rop(RegOps.GET_STATIC, Type.FLOAT, StdTypeList.EMPTY, - Exceptions.LIST_Error, "get-static-float"); - - /** - * <code>r: double; f: static field spec of type double :: r = - * f</code> - */ - public static final Rop GET_STATIC_DOUBLE = - new Rop(RegOps.GET_STATIC, Type.DOUBLE, StdTypeList.EMPTY, - Exceptions.LIST_Error, "get-static-double"); - - /** - * <code>r: Object; f: static field spec of type Object :: r = - * f</code> - */ - public static final Rop GET_STATIC_OBJECT = - new Rop(RegOps.GET_STATIC, Type.OBJECT, StdTypeList.EMPTY, - Exceptions.LIST_Error, "get-static-object"); - - /** - * <code>r: boolean; f: static field spec of type boolean :: r = - * f</code> - */ - public static final Rop GET_STATIC_BOOLEAN = - new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY, - Exceptions.LIST_Error, "get-field-boolean"); - - /** - * <code>r: byte; f: static field spec of type byte :: r = - * f</code> - */ - public static final Rop GET_STATIC_BYTE = - new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY, - Exceptions.LIST_Error, "get-field-byte"); - - /** - * <code>r: char; f: static field spec of type char :: r = - * f</code> - */ - public static final Rop GET_STATIC_CHAR = - new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY, - Exceptions.LIST_Error, "get-field-char"); - - /** - * <code>r: short; f: static field spec of type short :: r = - * f</code> - */ - public static final Rop GET_STATIC_SHORT = - new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY, - Exceptions.LIST_Error, "get-field-short"); - - /** - * <code>x: int; y: Object; f: instance field spec of type - * int :: y.f = x</code> - */ - public static final Rop PUT_FIELD_INT = - new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT, - Exceptions.LIST_Error_NullPointerException, "put-field-int"); - - /** - * <code>x: long; y: Object; f: instance field spec of type - * long :: y.f = x</code> - */ - public static final Rop PUT_FIELD_LONG = - new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.LONG_OBJECT, - Exceptions.LIST_Error_NullPointerException, "put-field-long"); - - /** - * <code>x: float; y: Object; f: instance field spec of type - * float :: y.f = x</code> - */ - public static final Rop PUT_FIELD_FLOAT = - new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.FLOAT_OBJECT, - Exceptions.LIST_Error_NullPointerException, - "put-field-float"); - - /** - * <code>x: double; y: Object; f: instance field spec of type - * double :: y.f = x</code> - */ - public static final Rop PUT_FIELD_DOUBLE = - new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.DOUBLE_OBJECT, - Exceptions.LIST_Error_NullPointerException, - "put-field-double"); - - /** - * <code>x: Object; y: Object; f: instance field spec of type - * Object :: y.f = x</code> - */ - public static final Rop PUT_FIELD_OBJECT = - new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.OBJECT_OBJECT, - Exceptions.LIST_Error_NullPointerException, - "put-field-object"); - - /** - * <code>x: int; y: Object; f: instance field spec of type - * boolean :: y.f = x</code> - */ - public static final Rop PUT_FIELD_BOOLEAN = - new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT, - Exceptions.LIST_Error_NullPointerException, - "put-field-boolean"); - - /** - * <code>x: int; y: Object; f: instance field spec of type - * byte :: y.f = x</code> - */ - public static final Rop PUT_FIELD_BYTE = - new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT, - Exceptions.LIST_Error_NullPointerException, - "put-field-byte"); - - /** - * <code>x: int; y: Object; f: instance field spec of type - * char :: y.f = x</code> - */ - public static final Rop PUT_FIELD_CHAR = - new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT, - Exceptions.LIST_Error_NullPointerException, - "put-field-char"); - - /** - * <code>x: int; y: Object; f: instance field spec of type - * short :: y.f = x</code> - */ - public static final Rop PUT_FIELD_SHORT = - new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT, - Exceptions.LIST_Error_NullPointerException, - "put-field-short"); - - /** - * <code>f: static field spec of type int; x: int :: f = - * x</code> - */ - public static final Rop PUT_STATIC_INT = - new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT, - Exceptions.LIST_Error, "put-static-int"); - - /** - * <code>f: static field spec of type long; x: long :: f = - * x</code> - */ - public static final Rop PUT_STATIC_LONG = - new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.LONG, - Exceptions.LIST_Error, "put-static-long"); - - /** - * <code>f: static field spec of type float; x: float :: f = - * x</code> - */ - public static final Rop PUT_STATIC_FLOAT = - new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.FLOAT, - Exceptions.LIST_Error, "put-static-float"); - - /** - * <code>f: static field spec of type double; x: double :: f = - * x</code> - */ - public static final Rop PUT_STATIC_DOUBLE = - new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.DOUBLE, - Exceptions.LIST_Error, "put-static-double"); - - /** - * <code>f: static field spec of type Object; x: Object :: f = - * x</code> - */ - public static final Rop PUT_STATIC_OBJECT = - new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.OBJECT, - Exceptions.LIST_Error, "put-static-object"); - - /** - * <code>f: static field spec of type boolean; x: boolean :: f = - * x</code> - */ - public static final Rop PUT_STATIC_BOOLEAN = - new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT, - Exceptions.LIST_Error, "put-static-boolean"); - - /** - * <code>f: static field spec of type byte; x: byte :: f = - * x</code> - */ - public static final Rop PUT_STATIC_BYTE = - new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT, - Exceptions.LIST_Error, "put-static-byte"); - - /** - * <code>f: static field spec of type char; x: char :: f = - * x</code> - */ - public static final Rop PUT_STATIC_CHAR = - new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT, - Exceptions.LIST_Error, "put-static-char"); - - /** - * <code>f: static field spec of type short; x: short :: f = - * x</code> - */ - public static final Rop PUT_STATIC_SHORT = - new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT, - Exceptions.LIST_Error, "put-static-short"); - - /** <code>x: Int :: local variable begins in x */ - public static final Rop MARK_LOCAL_INT = - new Rop (RegOps.MARK_LOCAL, Type.VOID, - StdTypeList.INT, "mark-local-int"); - - /** <code>x: Long :: local variable begins in x */ - public static final Rop MARK_LOCAL_LONG = - new Rop (RegOps.MARK_LOCAL, Type.VOID, - StdTypeList.LONG, "mark-local-long"); - - /** <code>x: Float :: local variable begins in x */ - public static final Rop MARK_LOCAL_FLOAT = - new Rop (RegOps.MARK_LOCAL, Type.VOID, - StdTypeList.FLOAT, "mark-local-float"); - - /** <code>x: Double :: local variable begins in x */ - public static final Rop MARK_LOCAL_DOUBLE = - new Rop (RegOps.MARK_LOCAL, Type.VOID, - StdTypeList.DOUBLE, "mark-local-double"); - - /** <code>x: Object :: local variable begins in x */ - public static final Rop MARK_LOCAL_OBJECT = - new Rop (RegOps.MARK_LOCAL, Type.VOID, - StdTypeList.OBJECT, "mark-local-object"); - - /** <code>T: Any primitive type; v0..vx: T :: {v0, ..., vx}</code> */ - public static final Rop FILL_ARRAY_DATA = - new Rop(RegOps.FILL_ARRAY_DATA, Type.VOID, StdTypeList.EMPTY, - "fill-array-data"); - - /** - * Returns the appropriate rop for the given opcode, destination, - * and sources. The result is typically, but not necessarily, a - * shared instance. - * - * <p><b>Note:</b> This method does not do complete error checking on - * its arguments, and so it may return an instance which seemed "right - * enough" even though in actuality the passed arguments don't quite - * match what is returned. TODO: Revisit this issue.</p> - * - * @param opcode the opcode - * @param dest non-null; destination type, or {@link Type#VOID} if none - * @param sources non-null; list of source types - * @param cst null-ok; associated constant, if any - * @return non-null; an appropriate instance - */ - public static Rop ropFor(int opcode, TypeBearer dest, TypeList sources, - Constant cst) { - switch (opcode) { - case RegOps.NOP: return NOP; - case RegOps.MOVE: return opMove(dest); - case RegOps.MOVE_PARAM: return opMoveParam(dest); - case RegOps.MOVE_EXCEPTION: return opMoveException(dest); - case RegOps.CONST: return opConst(dest); - case RegOps.GOTO: return GOTO; - case RegOps.IF_EQ: return opIfEq(sources); - case RegOps.IF_NE: return opIfNe(sources); - case RegOps.IF_LT: return opIfLt(sources); - case RegOps.IF_GE: return opIfGe(sources); - case RegOps.IF_LE: return opIfLe(sources); - case RegOps.IF_GT: return opIfGt(sources); - case RegOps.SWITCH: return SWITCH; - case RegOps.ADD: return opAdd(sources); - case RegOps.SUB: return opSub(sources); - case RegOps.MUL: return opMul(sources); - case RegOps.DIV: return opDiv(sources); - case RegOps.REM: return opRem(sources); - case RegOps.NEG: return opNeg(dest); - case RegOps.AND: return opAnd(sources); - case RegOps.OR: return opOr(sources); - case RegOps.XOR: return opXor(sources); - case RegOps.SHL: return opShl(sources); - case RegOps.SHR: return opShr(sources); - case RegOps.USHR: return opUshr(sources); - case RegOps.NOT: return opNot(dest); - case RegOps.CMPL: return opCmpl(sources.getType(0)); - case RegOps.CMPG: return opCmpg(sources.getType(0)); - case RegOps.CONV: return opConv(dest, sources.getType(0)); - case RegOps.TO_BYTE: return TO_BYTE; - case RegOps.TO_CHAR: return TO_CHAR; - case RegOps.TO_SHORT: return TO_SHORT; - case RegOps.RETURN: { - if (sources.size() == 0) { - return RETURN_VOID; - } - return opReturn(sources.getType(0)); - } - case RegOps.ARRAY_LENGTH: return ARRAY_LENGTH; - case RegOps.THROW: return THROW; - case RegOps.MONITOR_ENTER: return MONITOR_ENTER; - case RegOps.MONITOR_EXIT: return MONITOR_EXIT; - case RegOps.AGET: { - Type source = sources.getType(0); - if (source == Type.KNOWN_NULL) { - // Treat a known-null as an Object[] in this context. - source = Type.OBJECT_ARRAY; - } - return opAget(source.getComponentType()); - } - case RegOps.APUT: { - Type source = sources.getType(1); - if (source == Type.KNOWN_NULL) { - // Treat a known-null as an Object[] in this context. - source = Type.OBJECT_ARRAY; - } - return opAput(source.getComponentType()); - } - case RegOps.NEW_INSTANCE: return NEW_INSTANCE; - case RegOps.NEW_ARRAY: return opNewArray(dest.getType()); - case RegOps.CHECK_CAST: return CHECK_CAST; - case RegOps.INSTANCE_OF: return INSTANCE_OF; - case RegOps.GET_FIELD: return opGetField(dest); - case RegOps.GET_STATIC: return opGetStatic(dest); - case RegOps.PUT_FIELD: return opPutField(sources.getType(0)); - case RegOps.PUT_STATIC: return opPutStatic(sources.getType(0)); - case RegOps.INVOKE_STATIC: { - return opInvokeStatic(((CstMethodRef) cst).getPrototype()); - } - case RegOps.INVOKE_VIRTUAL: { - CstBaseMethodRef cstMeth = (CstMethodRef) cst; - Prototype meth = cstMeth.getPrototype(); - CstType definer = cstMeth.getDefiningClass(); - meth = meth.withFirstParameter(definer.getClassType()); - return opInvokeVirtual(meth); - } - case RegOps.INVOKE_SUPER: { - CstBaseMethodRef cstMeth = (CstMethodRef) cst; - Prototype meth = cstMeth.getPrototype(); - CstType definer = cstMeth.getDefiningClass(); - meth = meth.withFirstParameter(definer.getClassType()); - return opInvokeSuper(meth); - } - case RegOps.INVOKE_DIRECT: { - CstBaseMethodRef cstMeth = (CstMethodRef) cst; - Prototype meth = cstMeth.getPrototype(); - CstType definer = cstMeth.getDefiningClass(); - meth = meth.withFirstParameter(definer.getClassType()); - return opInvokeDirect(meth); - } - case RegOps.INVOKE_INTERFACE: { - CstBaseMethodRef cstMeth = (CstMethodRef) cst; - Prototype meth = cstMeth.getPrototype(); - CstType definer = cstMeth.getDefiningClass(); - meth = meth.withFirstParameter(definer.getClassType()); - return opInvokeInterface(meth); - } - } - - throw new RuntimeException("unknown opcode " + RegOps.opName(opcode)); - } - - /** - * Returns the appropriate <code>move</code> rop for the given type. The - * result is a shared instance. - * - * @param type non-null; type of value being moved - * @return non-null; an appropriate instance - */ - public static Rop opMove(TypeBearer type) { - switch (type.getBasicFrameType()) { - case Type.BT_INT: return MOVE_INT; - case Type.BT_LONG: return MOVE_LONG; - case Type.BT_FLOAT: return MOVE_FLOAT; - case Type.BT_DOUBLE: return MOVE_DOUBLE; - case Type.BT_OBJECT: return MOVE_OBJECT; - case Type.BT_ADDR: return MOVE_RETURN_ADDRESS; - } - - return throwBadType(type); - } - - /** - * Returns the appropriate <code>move-param</code> rop for the - * given type. The result is a shared instance. - * - * @param type non-null; type of value being moved - * @return non-null; an appropriate instance - */ - public static Rop opMoveParam(TypeBearer type) { - switch (type.getBasicFrameType()) { - case Type.BT_INT: return MOVE_PARAM_INT; - case Type.BT_LONG: return MOVE_PARAM_LONG; - case Type.BT_FLOAT: return MOVE_PARAM_FLOAT; - case Type.BT_DOUBLE: return MOVE_PARAM_DOUBLE; - case Type.BT_OBJECT: return MOVE_PARAM_OBJECT; - } - - return throwBadType(type); - } - - /** - * Returns the appropriate <code>move-exception</code> rop for the - * given type. The result may be a shared instance. - * - * @param type non-null; type of the exception - * @return non-null; an appropriate instance - */ - public static Rop opMoveException(TypeBearer type) { - return new Rop(RegOps.MOVE_EXCEPTION, type.getType(), - StdTypeList.EMPTY, (String) null); - } - - /** - * Returns the appropriate <code>move-result</code> rop for the - * given type. The result may be a shared instance. - * - * @param type non-null; type of the parameter - * @return non-null; an appropriate instance - */ - public static Rop opMoveResult(TypeBearer type) { - return new Rop(RegOps.MOVE_RESULT, type.getType(), - StdTypeList.EMPTY, (String) null); - } - - /** - * Returns the appropriate <code>move-result-pseudo</code> rop for the - * given type. The result may be a shared instance. - * - * @param type non-null; type of the parameter - * @return non-null; an appropriate instance - */ - public static Rop opMoveResultPseudo(TypeBearer type) { - return new Rop(RegOps.MOVE_RESULT_PSEUDO, type.getType(), - StdTypeList.EMPTY, (String) null); - } - - /** - * Returns the appropriate <code>const</code> rop for the given - * type. The result is a shared instance. - * - * @param type non-null; type of the constant - * @return non-null; an appropriate instance - */ - public static Rop opConst(TypeBearer type) { - if (type.getType() == Type.KNOWN_NULL) { - return CONST_OBJECT_NOTHROW; - } - - switch (type.getBasicFrameType()) { - case Type.BT_INT: return CONST_INT; - case Type.BT_LONG: return CONST_LONG; - case Type.BT_FLOAT: return CONST_FLOAT; - case Type.BT_DOUBLE: return CONST_DOUBLE; - case Type.BT_OBJECT: return CONST_OBJECT; - } - - return throwBadType(type); - } - - /** - * Returns the appropriate <code>if-eq</code> rop for the given - * sources. The result is a shared instance. - * - * @param types non-null; source types - * @return non-null; an appropriate instance - */ - public static Rop opIfEq(TypeList types) { - return pickIf(types, IF_EQZ_INT, IF_EQZ_OBJECT, - IF_EQ_INT, IF_EQ_OBJECT); - } - - /** - * Returns the appropriate <code>if-ne</code> rop for the given - * sources. The result is a shared instance. - * - * @param types non-null; source types - * @return non-null; an appropriate instance - */ - public static Rop opIfNe(TypeList types) { - return pickIf(types, IF_NEZ_INT, IF_NEZ_OBJECT, - IF_NE_INT, IF_NE_OBJECT); - } - - /** - * Returns the appropriate <code>if-lt</code> rop for the given - * sources. The result is a shared instance. - * - * @param types non-null; source types - * @return non-null; an appropriate instance - */ - public static Rop opIfLt(TypeList types) { - return pickIf(types, IF_LTZ_INT, null, IF_LT_INT, null); - } - - /** - * Returns the appropriate <code>if-ge</code> rop for the given - * sources. The result is a shared instance. - * - * @param types non-null; source types - * @return non-null; an appropriate instance - */ - public static Rop opIfGe(TypeList types) { - return pickIf(types, IF_GEZ_INT, null, IF_GE_INT, null); - } - - /** - * Returns the appropriate <code>if-gt</code> rop for the given - * sources. The result is a shared instance. - * - * @param types non-null; source types - * @return non-null; an appropriate instance - */ - public static Rop opIfGt(TypeList types) { - return pickIf(types, IF_GTZ_INT, null, IF_GT_INT, null); - } - - /** - * Returns the appropriate <code>if-le</code> rop for the given - * sources. The result is a shared instance. - * - * @param types non-null; source types - * @return non-null; an appropriate instance - */ - public static Rop opIfLe(TypeList types) { - return pickIf(types, IF_LEZ_INT, null, IF_LE_INT, null); - } - - /** - * Helper for all the <code>if*</code>-related methods, which - * checks types and picks one of the four variants, throwing if - * there's a problem. - * - * @param types non-null; the types - * @param intZ non-null; the int-to-0 comparison - * @param objZ null-ok; the object-to-null comparison - * @param intInt non-null; the int-to-int comparison - * @param objObj non-null; the object-to-object comparison - * @return non-null; the appropriate instance - */ - private static Rop pickIf(TypeList types, Rop intZ, Rop objZ, Rop intInt, - Rop objObj) { - switch(types.size()) { - case 1: { - switch (types.getType(0).getBasicFrameType()) { - case Type.BT_INT: { - return intZ; - } - case Type.BT_OBJECT: { - if (objZ != null) { - return objZ; - } - } - } - break; - } - case 2: { - int bt = types.getType(0).getBasicFrameType(); - if (bt == types.getType(1).getBasicFrameType()) { - switch (bt) { - case Type.BT_INT: { - return intInt; - } - case Type.BT_OBJECT: { - if (objObj != null) { - return objObj; - } - } - } - } - break; - } - } - - return throwBadTypes(types); - } - - /** - * Returns the appropriate <code>add</code> rop for the given - * types. The result is a shared instance. - * - * @param types non-null; types of the sources - * @return non-null; an appropriate instance - */ - public static Rop opAdd(TypeList types) { - return pickBinaryOp(types, ADD_CONST_INT, ADD_CONST_LONG, - ADD_CONST_FLOAT, ADD_CONST_DOUBLE, ADD_INT, - ADD_LONG, ADD_FLOAT, ADD_DOUBLE); - } - - /** - * Returns the appropriate <code>sub</code> rop for the given - * types. The result is a shared instance. - * - * @param types non-null; types of the sources - * @return non-null; an appropriate instance - */ - public static Rop opSub(TypeList types) { - return pickBinaryOp(types, SUB_CONST_INT, SUB_CONST_LONG, - SUB_CONST_FLOAT, SUB_CONST_DOUBLE, SUB_INT, - SUB_LONG, SUB_FLOAT, SUB_DOUBLE); - } - - /** - * Returns the appropriate <code>mul</code> rop for the given - * types. The result is a shared instance. - * - * @param types non-null; types of the sources - * @return non-null; an appropriate instance - */ - public static Rop opMul(TypeList types) { - return pickBinaryOp(types, MUL_CONST_INT, MUL_CONST_LONG, - MUL_CONST_FLOAT, MUL_CONST_DOUBLE, MUL_INT, - MUL_LONG, MUL_FLOAT, MUL_DOUBLE); - } - - /** - * Returns the appropriate <code>div</code> rop for the given - * types. The result is a shared instance. - * - * @param types non-null; types of the sources - * @return non-null; an appropriate instance - */ - public static Rop opDiv(TypeList types) { - return pickBinaryOp(types, DIV_CONST_INT, DIV_CONST_LONG, - DIV_CONST_FLOAT, DIV_CONST_DOUBLE, DIV_INT, - DIV_LONG, DIV_FLOAT, DIV_DOUBLE); - } - - /** - * Returns the appropriate <code>rem</code> rop for the given - * types. The result is a shared instance. - * - * @param types non-null; types of the sources - * @return non-null; an appropriate instance - */ - public static Rop opRem(TypeList types) { - return pickBinaryOp(types, REM_CONST_INT, REM_CONST_LONG, - REM_CONST_FLOAT, REM_CONST_DOUBLE, REM_INT, - REM_LONG, REM_FLOAT, REM_DOUBLE); - } - - /** - * Returns the appropriate <code>and</code> rop for the given - * types. The result is a shared instance. - * - * @param types non-null; types of the sources - * @return non-null; an appropriate instance - */ - public static Rop opAnd(TypeList types) { - return pickBinaryOp(types, AND_CONST_INT, AND_CONST_LONG, null, null, - AND_INT, AND_LONG, null, null); - } - - /** - * Returns the appropriate <code>or</code> rop for the given - * types. The result is a shared instance. - * - * @param types non-null; types of the sources - * @return non-null; an appropriate instance - */ - public static Rop opOr(TypeList types) { - return pickBinaryOp(types, OR_CONST_INT, OR_CONST_LONG, null, null, - OR_INT, OR_LONG, null, null); - } - - /** - * Returns the appropriate <code>xor</code> rop for the given - * types. The result is a shared instance. - * - * @param types non-null; types of the sources - * @return non-null; an appropriate instance - */ - public static Rop opXor(TypeList types) { - return pickBinaryOp(types, XOR_CONST_INT, XOR_CONST_LONG, null, null, - XOR_INT, XOR_LONG, null, null); - } - - /** - * Returns the appropriate <code>shl</code> rop for the given - * types. The result is a shared instance. - * - * @param types non-null; types of the sources - * @return non-null; an appropriate instance - */ - public static Rop opShl(TypeList types) { - return pickBinaryOp(types, SHL_CONST_INT, SHL_CONST_LONG, null, null, - SHL_INT, SHL_LONG, null, null); - } - - /** - * Returns the appropriate <code>shr</code> rop for the given - * types. The result is a shared instance. - * - * @param types non-null; types of the sources - * @return non-null; an appropriate instance - */ - public static Rop opShr(TypeList types) { - return pickBinaryOp(types, SHR_CONST_INT, SHR_CONST_LONG, null, null, - SHR_INT, SHR_LONG, null, null); - } - - /** - * Returns the appropriate <code>ushr</code> rop for the given - * types. The result is a shared instance. - * - * @param types non-null; types of the sources - * @return non-null; an appropriate instance - */ - public static Rop opUshr(TypeList types) { - return pickBinaryOp(types, USHR_CONST_INT, USHR_CONST_LONG, null, null, - USHR_INT, USHR_LONG, null, null); - } - - /** - * Returns the appropriate binary arithmetic rop for the given type - * and arguments. The result is a shared instance. - * - * @param types non-null; sources of the operation - * @param int1 non-null; the int-to-constant rop - * @param long1 non-null; the long-to-constant rop - * @param float1 null-ok; the float-to-constant rop, if any - * @param double1 null-ok; the double-to-constant rop, if any - * @param int2 non-null; the int-to-int rop - * @param long2 non-null; the long-to-long or long-to-int rop - * @param float2 null-ok; the float-to-float rop, if any - * @param double2 null-ok; the double-to-double rop, if any - * @return non-null; an appropriate instance - */ - private static Rop pickBinaryOp(TypeList types, Rop int1, Rop long1, - Rop float1, Rop double1, Rop int2, - Rop long2, Rop float2, Rop double2) { - int bt1 = types.getType(0).getBasicFrameType(); - Rop result = null; - - switch (types.size()) { - case 1: { - switch(bt1) { - case Type.BT_INT: return int1; - case Type.BT_LONG: return long1; - case Type.BT_FLOAT: result = float1; break; - case Type.BT_DOUBLE: result = double1; break; - } - break; - } - case 2: { - switch(bt1) { - case Type.BT_INT: return int2; - case Type.BT_LONG: return long2; - case Type.BT_FLOAT: result = float2; break; - case Type.BT_DOUBLE: result = double2; break; - } - break; - } - } - - if (result == null) { - return throwBadTypes(types); - } - - return result; - } - - /** - * Returns the appropriate <code>neg</code> rop for the given type. The - * result is a shared instance. - * - * @param type non-null; type of value being operated on - * @return non-null; an appropriate instance - */ - public static Rop opNeg(TypeBearer type) { - switch (type.getBasicFrameType()) { - case Type.BT_INT: return NEG_INT; - case Type.BT_LONG: return NEG_LONG; - case Type.BT_FLOAT: return NEG_FLOAT; - case Type.BT_DOUBLE: return NEG_DOUBLE; - } - - return throwBadType(type); - } - - /** - * Returns the appropriate <code>not</code> rop for the given type. The - * result is a shared instance. - * - * @param type non-null; type of value being operated on - * @return non-null; an appropriate instance - */ - public static Rop opNot(TypeBearer type) { - switch (type.getBasicFrameType()) { - case Type.BT_INT: return NOT_INT; - case Type.BT_LONG: return NOT_LONG; - } - - return throwBadType(type); - } - - /** - * Returns the appropriate <code>cmpl</code> rop for the given type. The - * result is a shared instance. - * - * @param type non-null; type of value being compared - * @return non-null; an appropriate instance - */ - public static Rop opCmpl(TypeBearer type) { - switch (type.getBasicType()) { - case Type.BT_LONG: return CMPL_LONG; - case Type.BT_FLOAT: return CMPL_FLOAT; - case Type.BT_DOUBLE: return CMPL_DOUBLE; - } - - return throwBadType(type); - } - - /** - * Returns the appropriate <code>cmpg</code> rop for the given type. The - * result is a shared instance. - * - * @param type non-null; type of value being compared - * @return non-null; an appropriate instance - */ - public static Rop opCmpg(TypeBearer type) { - switch (type.getBasicType()) { - case Type.BT_FLOAT: return CMPG_FLOAT; - case Type.BT_DOUBLE: return CMPG_DOUBLE; - } - - return throwBadType(type); - } - - /** - * Returns the appropriate <code>conv</code> rop for the given types. The - * result is a shared instance. - * - * @param dest non-null; target value type - * @param source non-null; source value type - * @return non-null; an appropriate instance - */ - public static Rop opConv(TypeBearer dest, TypeBearer source) { - int dbt = dest.getBasicFrameType(); - switch (source.getBasicFrameType()) { - case Type.BT_INT: { - switch (dbt) { - case Type.BT_LONG: return CONV_I2L; - case Type.BT_FLOAT: return CONV_I2F; - case Type.BT_DOUBLE: return CONV_I2D; - } - } - case Type.BT_LONG: { - switch (dbt) { - case Type.BT_INT: return CONV_L2I; - case Type.BT_FLOAT: return CONV_L2F; - case Type.BT_DOUBLE: return CONV_L2D; - } - } - case Type.BT_FLOAT: { - switch (dbt) { - case Type.BT_INT: return CONV_F2I; - case Type.BT_LONG: return CONV_F2L; - case Type.BT_DOUBLE: return CONV_F2D; - } - } - case Type.BT_DOUBLE: { - switch (dbt) { - case Type.BT_INT: return CONV_D2I; - case Type.BT_LONG: return CONV_D2L; - case Type.BT_FLOAT: return CONV_D2F; - } - } - } - - return throwBadTypes(StdTypeList.make(dest.getType(), - source.getType())); - } - - /** - * Returns the appropriate <code>return</code> rop for the given type. The - * result is a shared instance. - * - * @param type non-null; type of value being returned - * @return non-null; an appropriate instance - */ - public static Rop opReturn(TypeBearer type) { - switch (type.getBasicFrameType()) { - case Type.BT_INT: return RETURN_INT; - case Type.BT_LONG: return RETURN_LONG; - case Type.BT_FLOAT: return RETURN_FLOAT; - case Type.BT_DOUBLE: return RETURN_DOUBLE; - case Type.BT_OBJECT: return RETURN_OBJECT; - case Type.BT_VOID: return RETURN_VOID; - } - - return throwBadType(type); - } - - /** - * Returns the appropriate <code>aget</code> rop for the given type. The - * result is a shared instance. - * - * @param type non-null; element type of array being accessed - * @return non-null; an appropriate instance - */ - public static Rop opAget(TypeBearer type) { - switch (type.getBasicType()) { - case Type.BT_INT: return AGET_INT; - case Type.BT_LONG: return AGET_LONG; - case Type.BT_FLOAT: return AGET_FLOAT; - case Type.BT_DOUBLE: return AGET_DOUBLE; - case Type.BT_OBJECT: return AGET_OBJECT; - case Type.BT_BOOLEAN: return AGET_BOOLEAN; - case Type.BT_BYTE: return AGET_BYTE; - case Type.BT_CHAR: return AGET_CHAR; - case Type.BT_SHORT: return AGET_SHORT; - } - - return throwBadType(type); - } - - /** - * Returns the appropriate <code>aput</code> rop for the given type. The - * result is a shared instance. - * - * @param type non-null; element type of array being accessed - * @return non-null; an appropriate instance - */ - public static Rop opAput(TypeBearer type) { - switch (type.getBasicType()) { - case Type.BT_INT: return APUT_INT; - case Type.BT_LONG: return APUT_LONG; - case Type.BT_FLOAT: return APUT_FLOAT; - case Type.BT_DOUBLE: return APUT_DOUBLE; - case Type.BT_OBJECT: return APUT_OBJECT; - case Type.BT_BOOLEAN: return APUT_BOOLEAN; - case Type.BT_BYTE: return APUT_BYTE; - case Type.BT_CHAR: return APUT_CHAR; - case Type.BT_SHORT: return APUT_SHORT; - } - - return throwBadType(type); - } - - /** - * Returns the appropriate <code>new-array</code> rop for the given - * type. The result is a shared instance. - * - * @param arrayType non-null; array type of array being created - * @return non-null; an appropriate instance - */ - public static Rop opNewArray(TypeBearer arrayType) { - Type type = arrayType.getType(); - Type elementType = type.getComponentType(); - - switch (elementType.getBasicType()) { - case Type.BT_INT: return NEW_ARRAY_INT; - case Type.BT_LONG: return NEW_ARRAY_LONG; - case Type.BT_FLOAT: return NEW_ARRAY_FLOAT; - case Type.BT_DOUBLE: return NEW_ARRAY_DOUBLE; - case Type.BT_BOOLEAN: return NEW_ARRAY_BOOLEAN; - case Type.BT_BYTE: return NEW_ARRAY_BYTE; - case Type.BT_CHAR: return NEW_ARRAY_CHAR; - case Type.BT_SHORT: return NEW_ARRAY_SHORT; - case Type.BT_OBJECT: { - return new Rop(RegOps.NEW_ARRAY, type, StdTypeList.INT, - Exceptions.LIST_Error_NegativeArraySizeException, - "new-array-object"); - } - } - - return throwBadType(type); - } - - /** - * Returns the appropriate <code>filled-new-array</code> rop for the given - * type. The result may be a shared instance. - * - * @param arrayType non-null; type of array being created - * @param count >= 0; number of elements that the array should have - * @return non-null; an appropriate instance - */ - public static Rop opFilledNewArray(TypeBearer arrayType, int count) { - Type type = arrayType.getType(); - Type elementType = type.getComponentType(); - - if (elementType.isCategory2()) { - return throwBadType(arrayType); - } - - if (count < 0) { - throw new IllegalArgumentException("count < 0"); - } - - StdTypeList sourceTypes = new StdTypeList(count); - - for (int i = 0; i < count; i++) { - sourceTypes.set(i, elementType); - } - - // Note: The resulting rop is considered call-like. - return new Rop(RegOps.FILLED_NEW_ARRAY, - sourceTypes, - Exceptions.LIST_Error); - } - - /** - * Returns the appropriate <code>get-field</code> rop for the given - * type. The result is a shared instance. - * - * @param type non-null; type of the field in question - * @return non-null; an appropriate instance - */ - public static Rop opGetField(TypeBearer type) { - switch (type.getBasicType()) { - case Type.BT_INT: return GET_FIELD_INT; - case Type.BT_LONG: return GET_FIELD_LONG; - case Type.BT_FLOAT: return GET_FIELD_FLOAT; - case Type.BT_DOUBLE: return GET_FIELD_DOUBLE; - case Type.BT_OBJECT: return GET_FIELD_OBJECT; - case Type.BT_BOOLEAN: return GET_FIELD_BOOLEAN; - case Type.BT_BYTE: return GET_FIELD_BYTE; - case Type.BT_CHAR: return GET_FIELD_CHAR; - case Type.BT_SHORT: return GET_FIELD_SHORT; - } - - return throwBadType(type); - } - - /** - * Returns the appropriate <code>put-field</code> rop for the given - * type. The result is a shared instance. - * - * @param type non-null; type of the field in question - * @return non-null; an appropriate instance - */ - public static Rop opPutField(TypeBearer type) { - switch (type.getBasicType()) { - case Type.BT_INT: return PUT_FIELD_INT; - case Type.BT_LONG: return PUT_FIELD_LONG; - case Type.BT_FLOAT: return PUT_FIELD_FLOAT; - case Type.BT_DOUBLE: return PUT_FIELD_DOUBLE; - case Type.BT_OBJECT: return PUT_FIELD_OBJECT; - case Type.BT_BOOLEAN: return PUT_FIELD_BOOLEAN; - case Type.BT_BYTE: return PUT_FIELD_BYTE; - case Type.BT_CHAR: return PUT_FIELD_CHAR; - case Type.BT_SHORT: return PUT_FIELD_SHORT; - } - - return throwBadType(type); - } - - /** - * Returns the appropriate <code>get-static</code> rop for the given - * type. The result is a shared instance. - * - * @param type non-null; type of the field in question - * @return non-null; an appropriate instance - */ - public static Rop opGetStatic(TypeBearer type) { - switch (type.getBasicType()) { - case Type.BT_INT: return GET_STATIC_INT; - case Type.BT_LONG: return GET_STATIC_LONG; - case Type.BT_FLOAT: return GET_STATIC_FLOAT; - case Type.BT_DOUBLE: return GET_STATIC_DOUBLE; - case Type.BT_OBJECT: return GET_STATIC_OBJECT; - case Type.BT_BOOLEAN: return GET_STATIC_BOOLEAN; - case Type.BT_BYTE: return GET_STATIC_BYTE; - case Type.BT_CHAR: return GET_STATIC_CHAR; - case Type.BT_SHORT: return GET_STATIC_SHORT; - } - - return throwBadType(type); - } - - /** - * Returns the appropriate <code>put-static</code> rop for the given - * type. The result is a shared instance. - * - * @param type non-null; type of the field in question - * @return non-null; an appropriate instance - */ - public static Rop opPutStatic(TypeBearer type) { - switch (type.getBasicType()) { - case Type.BT_INT: return PUT_STATIC_INT; - case Type.BT_LONG: return PUT_STATIC_LONG; - case Type.BT_FLOAT: return PUT_STATIC_FLOAT; - case Type.BT_DOUBLE: return PUT_STATIC_DOUBLE; - case Type.BT_OBJECT: return PUT_STATIC_OBJECT; - case Type.BT_BOOLEAN: return PUT_STATIC_BOOLEAN; - case Type.BT_BYTE: return PUT_STATIC_BYTE; - case Type.BT_CHAR: return PUT_STATIC_CHAR; - case Type.BT_SHORT: return PUT_STATIC_SHORT; - } - - return throwBadType(type); - } - - /** - * Returns the appropriate <code>invoke-static</code> rop for the - * given type. The result is typically a newly-allocated instance. - * - * @param meth non-null; descriptor of the method - * @return non-null; an appropriate instance - */ - public static Rop opInvokeStatic(Prototype meth) { - return new Rop(RegOps.INVOKE_STATIC, - meth.getParameterFrameTypes(), - StdTypeList.THROWABLE); - } - - /** - * Returns the appropriate <code>invoke-virtual</code> rop for the - * given type. The result is typically a newly-allocated instance. - * - * @param meth non-null; descriptor of the method, including the - * <code>this</code> parameter - * @return non-null; an appropriate instance - */ - public static Rop opInvokeVirtual(Prototype meth) { - return new Rop(RegOps.INVOKE_VIRTUAL, - meth.getParameterFrameTypes(), - StdTypeList.THROWABLE); - } - - /** - * Returns the appropriate <code>invoke-super</code> rop for the - * given type. The result is typically a newly-allocated instance. - * - * @param meth non-null; descriptor of the method, including the - * <code>this</code> parameter - * @return non-null; an appropriate instance - */ - public static Rop opInvokeSuper(Prototype meth) { - return new Rop(RegOps.INVOKE_SUPER, - meth.getParameterFrameTypes(), - StdTypeList.THROWABLE); - } - - /** - * Returns the appropriate <code>invoke-direct</code> rop for the - * given type. The result is typically a newly-allocated instance. - * - * @param meth non-null; descriptor of the method, including the - * <code>this</code> parameter - * @return non-null; an appropriate instance - */ - public static Rop opInvokeDirect(Prototype meth) { - return new Rop(RegOps.INVOKE_DIRECT, - meth.getParameterFrameTypes(), - StdTypeList.THROWABLE); - } - - /** - * Returns the appropriate <code>invoke-interface</code> rop for the - * given type. The result is typically a newly-allocated instance. - * - * @param meth non-null; descriptor of the method, including the - * <code>this</code> parameter - * @return non-null; an appropriate instance - */ - public static Rop opInvokeInterface(Prototype meth) { - return new Rop(RegOps.INVOKE_INTERFACE, - meth.getParameterFrameTypes(), - StdTypeList.THROWABLE); - } - - /** - * Returns the appropriate <code>mark-local</code> rop for the given type. - * The result is a shared instance. - * - * @param type non-null; type of value being marked - * @return non-null; an appropriate instance - */ - public static Rop opMarkLocal(TypeBearer type) { - switch (type.getBasicFrameType()) { - case Type.BT_INT: return MARK_LOCAL_INT; - case Type.BT_LONG: return MARK_LOCAL_LONG; - case Type.BT_FLOAT: return MARK_LOCAL_FLOAT; - case Type.BT_DOUBLE: return MARK_LOCAL_DOUBLE; - case Type.BT_OBJECT: return MARK_LOCAL_OBJECT; - } - - return throwBadType(type); - } - - /** - * This class is uninstantiable. - */ - private Rops() { - // This space intentionally left blank. - } - - /** - * Throws the right exception to complain about a bogus type. - * - * @param type non-null; the bad type - * @return never - */ - private static Rop throwBadType(TypeBearer type) { - throw new IllegalArgumentException("bad type: " + type); - } - - /** - * Throws the right exception to complain about a bogus list of types. - * - * @param types non-null; the bad types - * @return never - */ - private static Rop throwBadTypes(TypeList types) { - throw new IllegalArgumentException("bad types: " + types); - } -} diff --git a/dx/src/com/android/dx/rop/code/SourcePosition.java b/dx/src/com/android/dx/rop/code/SourcePosition.java deleted file mode 100644 index da66c7de2..000000000 --- a/dx/src/com/android/dx/rop/code/SourcePosition.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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.cst.CstUtf8; -import com.android.dx.util.Hex; - -/** - * Information about a source position for code, which includes both a - * line number and original bytecode address. - */ -public final class SourcePosition { - /** non-null; convenient "no information known" instance */ - public static final SourcePosition NO_INFO = - new SourcePosition(null, -1, -1); - - /** null-ok; name of the file of origin or <code>null</code> if unknown */ - private final CstUtf8 sourceFile; - - /** - * >= -1; the bytecode address, or <code>-1</code> if that - * information is unknown - */ - private final int address; - - /** - * >= -1; the line number, or <code>-1</code> if that - * information is unknown - */ - private final int line; - - /** - * Constructs an instance. - * - * @param sourceFile null-ok; name of the file of origin or - * <code>null</code> if unknown - * @param address >= -1; original bytecode address or <code>-1</code> - * if unknown - * @param line >= -1; original line number or <code>-1</code> if - * unknown - */ - public SourcePosition(CstUtf8 sourceFile, int address, int line) { - if (address < -1) { - throw new IllegalArgumentException("address < -1"); - } - - if (line < -1) { - throw new IllegalArgumentException("line < -1"); - } - - this.sourceFile = sourceFile; - this.address = address; - this.line = line; - } - - /** {@inheritDoc} */ - @Override - public String toString() { - StringBuffer sb = new StringBuffer(50); - - if (sourceFile != null) { - sb.append(sourceFile.toHuman()); - sb.append(":"); - } - - if (line >= 0) { - sb.append(line); - } - - sb.append('@'); - - if (address < 0) { - sb.append("????"); - } else { - sb.append(Hex.u2(address)); - } - - return sb.toString(); - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - if (!(other instanceof SourcePosition)) { - return false; - } - - if (this == other) { - return true; - } - - SourcePosition pos = (SourcePosition) other; - - return (address == pos.address) && sameLineAndFile(pos); - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - return sourceFile.hashCode() + address + line; - } - - /** - * Returns whether the lines match between this instance and - * the one given. - * - * @param other non-null; the instance to compare to - * @return <code>true</code> iff the lines match - */ - public boolean sameLine(SourcePosition other) { - return (line == other.line); - } - - /** - * Returns whether the lines and files match between this instance and - * the one given. - * - * @param other non-null; the instance to compare to - * @return <code>true</code> iff the lines and files match - */ - public boolean sameLineAndFile(SourcePosition other) { - return (line == other.line) && - ((sourceFile == other.sourceFile) || - ((sourceFile != null) && sourceFile.equals(other.sourceFile))); - } - - /** - * Gets the source file, if known. - * - * @return null-ok; the source file or <code>null</code> if unknown - */ - public CstUtf8 getSourceFile() { - return sourceFile; - } - - /** - * Gets the original bytecode address. - * - * @return >= -1; the address or <code>-1</code> if unknown - */ - public int getAddress() { - return address; - } - - /** - * Gets the original line number. - * - * @return >= -1; the original line number or <code>-1</code> if - * unknown - */ - public int getLine() { - return line; - } -} diff --git a/dx/src/com/android/dx/rop/code/SwitchInsn.java b/dx/src/com/android/dx/rop/code/SwitchInsn.java deleted file mode 100644 index fdf1a468f..000000000 --- a/dx/src/com/android/dx/rop/code/SwitchInsn.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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.StdTypeList; -import com.android.dx.rop.type.Type; -import com.android.dx.rop.type.TypeList; -import com.android.dx.util.IntList; - -/** - * Instruction which contains switch cases. - */ -public final class SwitchInsn - extends Insn { - /** non-null; list of switch cases */ - private final IntList cases; - - /** - * Constructs an instance. - * - * @param opcode non-null; the opcode - * @param position non-null; source position - * @param result null-ok; spec for the result, if any - * @param sources non-null; specs for all the sources - * @param cases non-null; list of switch cases - */ - public SwitchInsn(Rop opcode, SourcePosition position, RegisterSpec result, - RegisterSpecList sources, IntList cases) { - super(opcode, position, result, sources); - - if (opcode.getBranchingness() != Rop.BRANCH_SWITCH) { - throw new IllegalArgumentException("bogus branchingness"); - } - - if (cases == null) { - throw new NullPointerException("cases == null"); - } - - this.cases = cases; - } - - /** {@inheritDoc} */ - @Override - public String getInlineString() { - return cases.toString(); - } - - /** {@inheritDoc} */ - @Override - public TypeList getCatches() { - return StdTypeList.EMPTY; - } - - /** {@inheritDoc} */ - @Override - public void accept(Visitor visitor) { - visitor.visitSwitchInsn(this); - } - - /** {@inheritDoc} */ - @Override - public Insn withAddedCatch(Type type) { - throw new UnsupportedOperationException("unsupported"); - } - - /** {@inheritDoc} */ - @Override - public Insn withRegisterOffset(int delta) { - return new SwitchInsn(getOpcode(), getPosition(), - getResult().withOffset(delta), - getSources().withOffset(delta), - cases); - } - - /** - * {@inheritDoc} - * - * <p> SwitchInsn always compares false. The current use for this method - * never encounters <code>SwitchInsn</code>s - */ - @Override - public boolean contentEquals(Insn b) { - return false; - } - - /** {@inheritDoc} */ - @Override - public Insn withNewRegisters(RegisterSpec result, - RegisterSpecList sources) { - - return new SwitchInsn(getOpcode(), getPosition(), - result, - sources, - cases); - } - - /** - * Gets the list of switch cases. - * - * @return non-null; the case list - */ - public IntList getCases() { - return cases; - } -} diff --git a/dx/src/com/android/dx/rop/code/ThrowingCstInsn.java b/dx/src/com/android/dx/rop/code/ThrowingCstInsn.java deleted file mode 100644 index 49ebc91a5..000000000 --- a/dx/src/com/android/dx/rop/code/ThrowingCstInsn.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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.cst.Constant; -import com.android.dx.rop.type.Type; -import com.android.dx.rop.type.TypeList; - -/** - * Instruction which contains an explicit reference to a constant - * and which might throw an exception. - */ -public final class ThrowingCstInsn - extends CstInsn { - /** non-null; list of exceptions caught */ - private final TypeList catches; - - /** - * Constructs an instance. - * - * @param opcode non-null; the opcode - * @param position non-null; source position - * @param sources non-null; specs for all the sources - * @param catches non-null; list of exceptions caught - * @param cst non-null; the constant - */ - public ThrowingCstInsn(Rop opcode, SourcePosition position, - RegisterSpecList sources, - TypeList catches, Constant cst) { - super(opcode, position, null, sources, cst); - - if (opcode.getBranchingness() != Rop.BRANCH_THROW) { - throw new IllegalArgumentException("bogus branchingness"); - } - - if (catches == null) { - throw new NullPointerException("catches == null"); - } - - this.catches = catches; - } - - /** {@inheritDoc} */ - @Override - public String getInlineString() { - return getConstant().toHuman() + " " + - ThrowingInsn.toCatchString(catches); - } - - /** {@inheritDoc} */ - @Override - public TypeList getCatches() { - return catches; - } - - /** {@inheritDoc} */ - @Override - public void accept(Visitor visitor) { - visitor.visitThrowingCstInsn(this); - } - - /** {@inheritDoc} */ - @Override - public Insn withAddedCatch(Type type) { - return new ThrowingCstInsn(getOpcode(), getPosition(), - getSources(), catches.withAddedType(type), - getConstant()); - } - - /** {@inheritDoc} */ - @Override - public Insn withRegisterOffset(int delta) { - return new ThrowingCstInsn(getOpcode(), getPosition(), - getSources().withOffset(delta), - catches, - getConstant()); - } - - /** {@inheritDoc} */ - @Override - public Insn withNewRegisters(RegisterSpec result, - RegisterSpecList sources) { - - return new ThrowingCstInsn(getOpcode(), getPosition(), - sources, - catches, - getConstant()); - } - - -} diff --git a/dx/src/com/android/dx/rop/code/ThrowingInsn.java b/dx/src/com/android/dx/rop/code/ThrowingInsn.java deleted file mode 100644 index 24a5bed9b..000000000 --- a/dx/src/com/android/dx/rop/code/ThrowingInsn.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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; - -/** - * Instruction which possibly throws. The <code>successors</code> list in the - * basic block an instance of this class is inside corresponds in-order to - * the list of exceptions handled by this instruction, with the - * no-exception case appended as the final target. - */ -public final class ThrowingInsn - extends Insn { - /** non-null; list of exceptions caught */ - private final TypeList catches; - - /** - * Gets the string form of a register spec list to be used as a catches - * list. - * - * @param catches non-null; the catches list - * @return non-null; the string form - */ - public static String toCatchString(TypeList catches) { - StringBuffer sb = new StringBuffer(100); - - sb.append("catch"); - - int sz = catches.size(); - for (int i = 0; i < sz; i++) { - sb.append(" "); - sb.append(catches.getType(i).toHuman()); - } - - return sb.toString(); - } - - /** - * Constructs an instance. - * - * @param opcode non-null; the opcode - * @param position non-null; source position - * @param sources non-null; specs for all the sources - * @param catches non-null; list of exceptions caught - */ - public ThrowingInsn(Rop opcode, SourcePosition position, - RegisterSpecList sources, - TypeList catches) { - super(opcode, position, null, sources); - - if (opcode.getBranchingness() != Rop.BRANCH_THROW) { - throw new IllegalArgumentException("bogus branchingness"); - } - - if (catches == null) { - throw new NullPointerException("catches == null"); - } - - this.catches = catches; - } - - /** {@inheritDoc} */ - @Override - public String getInlineString() { - return toCatchString(catches); - } - - /** {@inheritDoc} */ - @Override - public TypeList getCatches() { - return catches; - } - - /** {@inheritDoc} */ - @Override - public void accept(Visitor visitor) { - visitor.visitThrowingInsn(this); - } - - /** {@inheritDoc} */ - @Override - public Insn withAddedCatch(Type type) { - return new ThrowingInsn(getOpcode(), getPosition(), - getSources(), catches.withAddedType(type)); - } - - /** {@inheritDoc} */ - @Override - public Insn withRegisterOffset(int delta) { - return new ThrowingInsn(getOpcode(), getPosition(), - getSources().withOffset(delta), - catches); - } - - /** {@inheritDoc} */ - @Override - public Insn withNewRegisters(RegisterSpec result, - RegisterSpecList sources) { - - return new ThrowingInsn(getOpcode(), getPosition(), - sources, - catches); - } -} diff --git a/dx/src/com/android/dx/rop/code/TranslationAdvice.java b/dx/src/com/android/dx/rop/code/TranslationAdvice.java deleted file mode 100644 index 8c2cde984..000000000 --- a/dx/src/com/android/dx/rop/code/TranslationAdvice.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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; - -/** - * Interface for "advice" passed from the late stage of translation back - * to the early stage. This allows for the final target architecture to - * exert its influence early in the translation process without having - * the early stage code be explicitly tied to the target. - */ -public interface TranslationAdvice { - /** - * Returns an indication of whether the target can directly represent an - * instruction with the given opcode operating on the given arguments, - * where the last source argument is used as a constant. (That is, the - * last argument must have a type which indicates it is a known constant.) - * The instruction associated must have exactly two sources. - * - * @param opcode non-null; the opcode - * @param sourceA non-null; the first source - * @param sourceB non-null; the second source - * @return <code>true</code> iff the target can represent the operation - * using a constant for the last argument - */ - public boolean hasConstantOperation(Rop opcode, - RegisterSpec sourceA, RegisterSpec sourceB); - - /** - * Returns true if the translation target requires the sources of the - * specified opcode to be in order and contiguous (eg, for an invoke-range) - * - * @param opcode non-null; opcode - * @param sources non-null; source list - * @return <code>true</code> iff the target requires the sources to be - * in order and contiguous. - */ - public boolean requiresSourcesInOrder(Rop opcode, RegisterSpecList sources); - - /** - * Gets the maximum register width that can be represented optimally. - * For example, Dex bytecode does not have instruction forms that take - * register numbers larger than 15 for all instructions so - * DexTranslationAdvice returns 15 here. - * - * @return register count noted above - */ - public int getMaxOptimalRegisterCount(); -} diff --git a/dx/src/com/android/dx/rop/code/package.html b/dx/src/com/android/dx/rop/code/package.html deleted file mode 100644 index 86566b497..000000000 --- a/dx/src/com/android/dx/rop/code/package.html +++ /dev/null @@ -1,8 +0,0 @@ -<body> -<p>Classes relating to a register-based opcode system.</p> - -<p><b>PACKAGES USED:</b> -<ul> -<li><code>com.android.dx.util</code></li> -</ul> -</body> diff --git a/dx/src/com/android/dx/rop/cst/Constant.java b/dx/src/com/android/dx/rop/cst/Constant.java deleted file mode 100644 index 0f440103c..000000000 --- a/dx/src/com/android/dx/rop/cst/Constant.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.util.ToHuman; - -/** - * Base class for constants of all sorts. - */ -public abstract class Constant - implements ToHuman, Comparable<Constant> { - /** - * Returns <code>true</code> if this instance is a category-2 constant, - * meaning it takes up two slots in the constant pool, or - * <code>false</code> if this instance is category-1. - * - * @return <code>true</code> iff this instance is category-2 - */ - public abstract boolean isCategory2(); - - /** - * Returns the human name for the particular type of constant - * this instance is. - * - * @return non-null; the name - */ - public abstract String typeName(); - - /** - * {@inheritDoc} - * - * This compares in class-major and value-minor order. - */ - public final int compareTo(Constant other) { - Class clazz = getClass(); - Class otherClazz = other.getClass(); - - if (clazz != otherClazz) { - return clazz.getName().compareTo(otherClazz.getName()); - } - - return compareTo0(other); - } - - /** - * Compare the values of this and another instance, which are guaranteed - * to be of the same class. Subclasses must implement this. - * - * @param other non-null; the instance to compare to - * @return <code>-1</code>, <code>0</code>, or <code>1</code>, as usual - * for a comparison - */ - protected abstract int compareTo0(Constant other); -} diff --git a/dx/src/com/android/dx/rop/cst/ConstantPool.java b/dx/src/com/android/dx/rop/cst/ConstantPool.java deleted file mode 100644 index 9a64a2aab..000000000 --- a/dx/src/com/android/dx/rop/cst/ConstantPool.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.cst; - -/** - * Interface for constant pools, which are, more or less, just lists of - * {@link Constant} objects. - */ -public interface ConstantPool { - /** - * Get the "size" of the constant pool. This corresponds to the - * class file field <code>constant_pool_count</code>, and is in fact - * always at least one more than the actual size of the constant pool, - * as element <code>0</code> is always invalid. - * - * @return <code>>= 1</code>; the size - */ - public int size(); - - /** - * Get the <code>n</code>th entry in the constant pool, which must - * be valid. - * - * @param n <code>n >= 0, n < size()</code>; the constant pool index - * @return non-null; the corresponding entry - * @throws IllegalArgumentException thrown if <code>n</code> is - * in-range but invalid - */ - public Constant get(int n); - - /** - * Get the <code>n</code>th entry in the constant pool, which must - * be valid unless <code>n == 0</code>, in which case <code>null</code> - * is returned. - * - * @param n <code>n >= 0, n < size()</code>; the constant pool index - * @return null-ok; the corresponding entry, if <code>n != 0</code> - * @throws IllegalArgumentException thrown if <code>n</code> is - * in-range and non-zero but invalid - */ - public Constant get0Ok(int n); - - /** - * Get the <code>n</code>th entry in the constant pool, or - * <code>null</code> if the index is in-range but invalid. In - * particular, <code>null</code> is returned for index <code>0</code> - * as well as the index after any entry which is defined to take up - * two slots (that is, <code>Long</code> and <code>Double</code> - * entries). - * - * @param n <code>n >= 0, n < size()</code>; the constant pool index - * @return null-ok; the corresponding entry, or <code>null</code> if - * the index is in-range but invalid - */ - public Constant getOrNull(int n); -} diff --git a/dx/src/com/android/dx/rop/cst/CstAnnotation.java b/dx/src/com/android/dx/rop/cst/CstAnnotation.java deleted file mode 100644 index d6dc1f255..000000000 --- a/dx/src/com/android/dx/rop/cst/CstAnnotation.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.annotation.Annotation; - -/** - * Constant type that represents an annotation. - */ -public final class CstAnnotation extends Constant { - /** non-null; the actual annotation */ - private final Annotation annotation; - - /** - * Constructs an instance. - * - * @param annotation non-null; the annotation to hold - */ - public CstAnnotation(Annotation annotation) { - if (annotation == null) { - throw new NullPointerException("annotation == null"); - } - - annotation.throwIfMutable(); - - this.annotation = annotation; - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - if (! (other instanceof CstAnnotation)) { - return false; - } - - return annotation.equals(((CstAnnotation) other).annotation); - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - return annotation.hashCode(); - } - - /** {@inheritDoc} */ - @Override - protected int compareTo0(Constant other) { - return annotation.compareTo(((CstAnnotation) other).annotation); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return annotation.toString(); - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "annotation"; - } - - /** {@inheritDoc} */ - @Override - public boolean isCategory2() { - return false; - } - - /** {@inheritDoc} */ - public String toHuman() { - return annotation.toString(); - } - - /** - * Get the underlying annotation. - * - * @return non-null; the annotation - */ - public Annotation getAnnotation() { - return annotation; - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstArray.java b/dx/src/com/android/dx/rop/cst/CstArray.java deleted file mode 100644 index 69c0aeffa..000000000 --- a/dx/src/com/android/dx/rop/cst/CstArray.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.Type; -import com.android.dx.util.FixedSizeList; - -/** - * Constant type to represent a fixed array of other constants. The contents - * may be of any type <i>other</i> than {@link CstUtf8}. - */ -public final class CstArray extends Constant { - /** non-null; the actual list of contents */ - private final List list; - - /** - * Constructs an instance. - * - * @param list non-null; the actual list of contents - */ - public CstArray(List list) { - if (list == null) { - throw new NullPointerException("list == null"); - } - - list.throwIfMutable(); - - this.list = list; - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - if (! (other instanceof CstArray)) { - return false; - } - - return list.equals(((CstArray) other).list); - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - return list.hashCode(); - } - - /** {@inheritDoc} */ - @Override - protected int compareTo0(Constant other) { - return list.compareTo(((CstArray) other).list); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return list.toString("array{", ", ", "}"); - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "array"; - } - - /** {@inheritDoc} */ - @Override - public boolean isCategory2() { - return false; - } - - /** {@inheritDoc} */ - public String toHuman() { - return list.toHuman("{", ", ", "}"); - } - - /** - * Get the underlying list. - * - * @return non-null; the list - */ - public List getList() { - return list; - } - - /** - * List of {@link Constant} instances. - */ - public static final class List - extends FixedSizeList implements Comparable<List> { - /** - * Constructs an instance. All indices initially contain - * <code>null</code>. - * - * @param size the size of the list - */ - public List(int size) { - super(size); - } - - /** {@inheritDoc} */ - public int compareTo(List other) { - int thisSize = size(); - int otherSize = other.size(); - int compareSize = (thisSize < otherSize) ? thisSize : otherSize; - - for (int i = 0; i < compareSize; i++) { - Constant thisItem = (Constant) get0(i); - Constant otherItem = (Constant) other.get0(i); - int compare = thisItem.compareTo(otherItem); - if (compare != 0) { - return compare; - } - } - - if (thisSize < otherSize) { - return -1; - } else if (thisSize > otherSize) { - return 1; - } - - return 0; - } - - /** - * Gets the element at the given index. 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</code>. - * - * @param n >= 0, < size(); which index - * @return non-null; element at that index - */ - public Constant get(int n) { - return (Constant) get0(n); - } - - /** - * Sets the element at the given index. - * - * @param n >= 0, < size(); which index - * @param a null-ok; the element to set at <code>n</code> - */ - public void set(int n, Constant a) { - if (a instanceof CstUtf8) { - throw new IllegalArgumentException("bad value: " + a); - } - - set0(n, a); - } - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstBaseMethodRef.java b/dx/src/com/android/dx/rop/cst/CstBaseMethodRef.java deleted file mode 100644 index c8856019d..000000000 --- a/dx/src/com/android/dx/rop/cst/CstBaseMethodRef.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.Prototype; -import com.android.dx.rop.type.Type; -import com.android.dx.rop.type.TypeBearer; - -/** - * Base class for constants of "methodish" type. - * - * <p><b>Note:</b> As a {@link TypeBearer}, this class bears the return type - * of the method.</p> - */ -public abstract class CstBaseMethodRef - extends CstMemberRef { - /** non-null; the raw prototype for this method */ - private final Prototype prototype; - - /** - * null-ok; the prototype for this method taken to be an instance - * method, or <code>null</code> if not yet calculated - */ - private Prototype instancePrototype; - - /** - * Constructs an instance. - * - * @param definingClass non-null; the type of the defining class - * @param nat non-null; the name-and-type - */ - /*package*/ CstBaseMethodRef(CstType definingClass, CstNat nat) { - super(definingClass, nat); - - String descriptor = getNat().getDescriptor().getString(); - this.prototype = Prototype.intern(descriptor); - this.instancePrototype = null; - } - - /** - * Gets the raw prototype of this method. This doesn't include a - * <code>this</code> argument. - * - * @return non-null; the method prototype - */ - public final Prototype getPrototype() { - return prototype; - } - - /** - * Gets the prototype of this method as either a - * <code>static</code> or instance method. In the case of a - * <code>static</code> method, this is the same as the raw - * prototype. In the case of an instance method, this has an - * appropriately-typed <code>this</code> argument as the first - * one. - * - * @param isStatic whether the method should be considered static - * @return non-null; the method prototype - */ - public final Prototype getPrototype(boolean isStatic) { - if (isStatic) { - return prototype; - } else { - if (instancePrototype == null) { - Type thisType = getDefiningClass().getClassType(); - instancePrototype = prototype.withFirstParameter(thisType); - } - return instancePrototype; - } - } - - /** {@inheritDoc} */ - @Override - protected final int compareTo0(Constant other) { - int cmp = super.compareTo0(other); - - if (cmp != 0) { - return cmp; - } - - CstBaseMethodRef otherMethod = (CstBaseMethodRef) other; - return prototype.compareTo(otherMethod.prototype); - } - - /** - * {@inheritDoc} - * - * In this case, this method returns the <i>return type</i> of this method. - * - * @return non-null; the method's return type - */ - public final Type getType() { - return prototype.getReturnType(); - } - - /** - * Gets the number of words of parameters required by this - * method's descriptor. Since instances of this class have no way - * to know if they will be used in a <code>static</code> or - * instance context, one has to indicate this explicitly as an - * argument. This method is just a convenient shorthand for - * <code>getPrototype().getParameterTypes().getWordCount()</code>, - * plus <code>1</code> if the method is to be treated as an - * instance method. - * - * @param isStatic whether the method should be considered static - * @return >= 0; the argument word count - */ - public final int getParameterWordCount(boolean isStatic) { - return getPrototype(isStatic).getParameterTypes().getWordCount(); - } - - /** - * Gets whether this is a reference to an instance initialization - * method. This is just a convenient shorthand for - * <code>getNat().isInstanceInit()</code>. - * - * @return <code>true</code> iff this is a reference to an - * instance initialization method - */ - public final boolean isInstanceInit() { - return getNat().isInstanceInit(); - } - - /** - * Gets whether this is a reference to a class initialization - * method. This is just a convenient shorthand for - * <code>getNat().isClassInit()</code>. - * - * @return <code>true</code> iff this is a reference to an - * instance initialization method - */ - public final boolean isClassInit() { - return getNat().isClassInit(); - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstBoolean.java b/dx/src/com/android/dx/rop/cst/CstBoolean.java deleted file mode 100644 index ab25d5bcf..000000000 --- a/dx/src/com/android/dx/rop/cst/CstBoolean.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.Type; - -/** - * Constants of type <code>boolean</code>. - */ -public final class CstBoolean - extends CstLiteral32 { - /** non-null; instance representing <code>false</code> */ - public static final CstBoolean VALUE_FALSE = new CstBoolean(false); - - /** non-null; instance representing <code>true</code> */ - public static final CstBoolean VALUE_TRUE = new CstBoolean(true); - - /** - * Makes an instance for the given value. This will return an - * already-allocated instance. - * - * @param value the <code>boolean</code> value - * @return non-null; the appropriate instance - */ - public static CstBoolean make(boolean value) { - return value ? VALUE_TRUE : VALUE_FALSE; - } - - /** - * Makes an instance for the given <code>int</code> value. This - * will return an already-allocated instance. - * - * @param value must be either <code>0</code> or <code>1</code> - * @return non-null; the appropriate instance - */ - public static CstBoolean make(int value) { - if (value == 0) { - return VALUE_FALSE; - } else if (value == 1) { - return VALUE_TRUE; - } else { - throw new IllegalArgumentException("bogus value: " + value); - } - } - - /** - * Constructs an instance. This constructor is private; use {@link #make}. - * - * @param value the <code>boolean</code> value - */ - private CstBoolean(boolean value) { - super(value ? 1 : 0); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return getValue() ? "boolean{true}" : "boolean{false}"; - } - - /** {@inheritDoc} */ - public Type getType() { - return Type.BOOLEAN; - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "boolean"; - } - - /** {@inheritDoc} */ - public String toHuman() { - return getValue() ? "true" : "false"; - } - - /** - * Gets the <code>boolean</code> value. - * - * @return the value - */ - public boolean getValue() { - return (getIntBits() == 0) ? false : true; - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstByte.java b/dx/src/com/android/dx/rop/cst/CstByte.java deleted file mode 100644 index ffc3206b6..000000000 --- a/dx/src/com/android/dx/rop/cst/CstByte.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.Type; -import com.android.dx.util.Hex; - -/** - * Constants of type <code>byte</code>. - */ -public final class CstByte - extends CstLiteral32 { - /** non-null; the value <code>0</code> as an instance of this class */ - public static final CstByte VALUE_0 = make((byte) 0); - - /** - * Makes an instance for the given value. This may (but does not - * necessarily) return an already-allocated instance. - * - * @param value the <code>byte</code> value - */ - public static CstByte make(byte value) { - return new CstByte(value); - } - - /** - * Makes an instance for the given <code>int</code> value. This - * may (but does not necessarily) return an already-allocated - * instance. - * - * @param value the value, which must be in range for a <code>byte</code> - * @return non-null; the appropriate instance - */ - public static CstByte make(int value) { - byte cast = (byte) value; - - if (cast != value) { - throw new IllegalArgumentException("bogus byte value: " + - value); - } - - return make(cast); - } - - /** - * Constructs an instance. This constructor is private; use {@link #make}. - * - * @param value the <code>byte</code> value - */ - private CstByte(byte value) { - super(value); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - int value = getIntBits(); - return "byte{0x" + Hex.u1(value) + " / " + value + '}'; - } - - /** {@inheritDoc} */ - public Type getType() { - return Type.BYTE; - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "byte"; - } - - /** {@inheritDoc} */ - public String toHuman() { - return Integer.toString(getIntBits()); - } - - /** - * Gets the <code>byte</code> value. - * - * @return the value - */ - public byte getValue() { - return (byte) getIntBits(); - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstChar.java b/dx/src/com/android/dx/rop/cst/CstChar.java deleted file mode 100644 index a31bd7fc0..000000000 --- a/dx/src/com/android/dx/rop/cst/CstChar.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.Type; -import com.android.dx.util.Hex; - -/** - * Constants of type <code>char</code>. - */ -public final class CstChar - extends CstLiteral32 { - /** non-null; the value <code>0</code> as an instance of this class */ - public static final CstChar VALUE_0 = make((char) 0); - - /** - * Makes an instance for the given value. This may (but does not - * necessarily) return an already-allocated instance. - * - * @param value the <code>char</code> value - */ - public static CstChar make(char value) { - return new CstChar(value); - } - - /** - * Makes an instance for the given <code>int</code> value. This - * may (but does not necessarily) return an already-allocated - * instance. - * - * @param value the value, which must be in range for a <code>char</code> - * @return non-null; the appropriate instance - */ - public static CstChar make(int value) { - char cast = (char) value; - - if (cast != value) { - throw new IllegalArgumentException("bogus char value: " + - value); - } - - return make(cast); - } - - /** - * Constructs an instance. This constructor is private; use {@link #make}. - * - * @param value the <code>char</code> value - */ - private CstChar(char value) { - super(value); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - int value = getIntBits(); - return "char{0x" + Hex.u2(value) + " / " + value + '}'; - } - - /** {@inheritDoc} */ - public Type getType() { - return Type.CHAR; - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "char"; - } - - /** {@inheritDoc} */ - public String toHuman() { - return Integer.toString(getIntBits()); - } - - /** - * Gets the <code>char</code> value. - * - * @return the value - */ - public char getValue() { - return (char) getIntBits(); - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstDouble.java b/dx/src/com/android/dx/rop/cst/CstDouble.java deleted file mode 100644 index 451666791..000000000 --- a/dx/src/com/android/dx/rop/cst/CstDouble.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.Type; -import com.android.dx.util.Hex; - -/** - * Constants of type <code>CONSTANT_Double_info</code>. - */ -public final class CstDouble - extends CstLiteral64 { - /** non-null; instance representing <code>0</code> */ - public static final CstDouble VALUE_0 = - new CstDouble(Double.doubleToLongBits(0.0)); - - /** non-null; instance representing <code>1</code> */ - public static final CstDouble VALUE_1 = - new CstDouble(Double.doubleToLongBits(1.0)); - - /** - * Makes an instance for the given value. This may (but does not - * necessarily) return an already-allocated instance. - * - * @param bits the <code>double</code> value as <code>long</code> bits - */ - public static CstDouble make(long bits) { - /* - * Note: Javadoc notwithstanding, this implementation always - * allocates. - */ - return new CstDouble(bits); - } - - /** - * Constructs an instance. This constructor is private; use {@link #make}. - * - * @param bits the <code>double</code> value as <code>long</code> bits - */ - private CstDouble(long bits) { - super(bits); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - long bits = getLongBits(); - return "double{0x" + Hex.u8(bits) + " / " + - Double.longBitsToDouble(bits) + '}'; - } - - /** {@inheritDoc} */ - public Type getType() { - return Type.DOUBLE; - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "double"; - } - - /** {@inheritDoc} */ - public String toHuman() { - return Double.toString(Double.longBitsToDouble(getLongBits())); - } - - /** - * Gets the <code>double</code> value. - * - * @return the value - */ - public double getValue() { - return Double.longBitsToDouble(getLongBits()); - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstEnumRef.java b/dx/src/com/android/dx/rop/cst/CstEnumRef.java deleted file mode 100644 index f5aec0549..000000000 --- a/dx/src/com/android/dx/rop/cst/CstEnumRef.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2008 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.cst; - -import com.android.dx.rop.type.Type; - -/** - * Constant type to represent a reference to a particular constant - * value of an enumerated type. - */ -public final class CstEnumRef extends CstMemberRef { - /** null-ok; the corresponding field ref, lazily initialized */ - private CstFieldRef fieldRef; - - /** - * Constructs an instance. - * - * @param nat non-null; the name-and-type; the defining class is derived - * from this - */ - public CstEnumRef(CstNat nat) { - super(new CstType(nat.getFieldType()), nat); - - fieldRef = null; - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "enum"; - } - - /** - * {@inheritDoc} - * - * <b>Note:</b> This returns the enumerated type. - */ - public Type getType() { - return getDefiningClass().getClassType(); - } - - /** - * Get a {@link CstFieldRef} that corresponds with this instance. - * - * @return non-null; the corresponding field reference - */ - public CstFieldRef getFieldRef() { - if (fieldRef == null) { - fieldRef = new CstFieldRef(getDefiningClass(), getNat()); - } - - return fieldRef; - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstFieldRef.java b/dx/src/com/android/dx/rop/cst/CstFieldRef.java deleted file mode 100644 index 306eca928..000000000 --- a/dx/src/com/android/dx/rop/cst/CstFieldRef.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.Type; - -/** - * Constants of type <code>CONSTANT_Fieldref_info</code>. - */ -public final class CstFieldRef extends CstMemberRef { - /** - * Returns an instance of this class that represents the static - * field which should hold the class corresponding to a given - * primitive type. For example, if given {@link Type#INT}, this - * method returns an instance corresponding to the field - * <code>java.lang.Integer.TYPE</code>. - * - * @param primitiveType non-null; the primitive type - * @return non-null; the corresponding static field - */ - public static CstFieldRef forPrimitiveType(Type primitiveType) { - return new CstFieldRef(CstType.forBoxedPrimitiveType(primitiveType), - CstNat.PRIMITIVE_TYPE_NAT); - } - - /** - * Constructs an instance. - * - * @param definingClass non-null; the type of the defining class - * @param nat non-null; the name-and-type - */ - public CstFieldRef(CstType definingClass, CstNat nat) { - super(definingClass, nat); - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "field"; - } - - /** - * Returns the type of this field. - * - * @return non-null; the field's type - */ - public Type getType() { - return getNat().getFieldType(); - } - - /** {@inheritDoc} */ - @Override - protected int compareTo0(Constant other) { - int cmp = super.compareTo0(other); - - if (cmp != 0) { - return cmp; - } - - CstFieldRef otherField = (CstFieldRef) other; - CstUtf8 thisDescriptor = getNat().getDescriptor(); - CstUtf8 otherDescriptor = otherField.getNat().getDescriptor(); - return thisDescriptor.compareTo(otherDescriptor); - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstFloat.java b/dx/src/com/android/dx/rop/cst/CstFloat.java deleted file mode 100644 index 08b7f764e..000000000 --- a/dx/src/com/android/dx/rop/cst/CstFloat.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.Type; -import com.android.dx.util.Hex; - -/** - * Constants of type <code>CONSTANT_Float_info</code>. - */ -public final class CstFloat - extends CstLiteral32 { - /** non-null; instance representing <code>0</code> */ - public static final CstFloat VALUE_0 = make(Float.floatToIntBits(0.0f)); - - /** non-null; instance representing <code>1</code> */ - public static final CstFloat VALUE_1 = make(Float.floatToIntBits(1.0f)); - - /** non-null; instance representing <code>2</code> */ - public static final CstFloat VALUE_2 = make(Float.floatToIntBits(2.0f)); - - /** - * Makes an instance for the given value. This may (but does not - * necessarily) return an already-allocated instance. - * - * @param bits the <code>float</code> value as <code>int</code> bits - */ - public static CstFloat make(int bits) { - /* - * Note: Javadoc notwithstanding, this implementation always - * allocates. - */ - return new CstFloat(bits); - } - - /** - * Constructs an instance. This constructor is private; use {@link #make}. - * - * @param bits the <code>float</code> value as <code>int</code> bits - */ - private CstFloat(int bits) { - super(bits); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - int bits = getIntBits(); - return "float{0x" + Hex.u4(bits) + " / " + - Float.intBitsToFloat(bits) + '}'; - } - - /** {@inheritDoc} */ - public Type getType() { - return Type.FLOAT; - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "float"; - } - - /** {@inheritDoc} */ - public String toHuman() { - return Float.toString(Float.intBitsToFloat(getIntBits())); - } - - /** - * Gets the <code>float</code> value. - * - * @return the value - */ - public float getValue() { - return Float.intBitsToFloat(getIntBits()); - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstInteger.java b/dx/src/com/android/dx/rop/cst/CstInteger.java deleted file mode 100644 index d3fafccd7..000000000 --- a/dx/src/com/android/dx/rop/cst/CstInteger.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.Type; -import com.android.dx.util.Hex; - -/** - * Constants of type <code>CONSTANT_Integer_info</code>. - */ -public final class CstInteger - extends CstLiteral32 { - /** non-null; array of cached instances */ - private static final CstInteger[] cache = new CstInteger[511]; - - /** non-null; instance representing <code>-1</code> */ - public static final CstInteger VALUE_M1 = make(-1); - - /** non-null; instance representing <code>0</code> */ - public static final CstInteger VALUE_0 = make(0); - - /** non-null; instance representing <code>1</code> */ - public static final CstInteger VALUE_1 = make(1); - - /** non-null; instance representing <code>2</code> */ - public static final CstInteger VALUE_2 = make(2); - - /** non-null; instance representing <code>3</code> */ - public static final CstInteger VALUE_3 = make(3); - - /** non-null; instance representing <code>4</code> */ - public static final CstInteger VALUE_4 = make(4); - - /** non-null; instance representing <code>5</code> */ - public static final CstInteger VALUE_5 = make(5); - - /** - * Makes an instance for the given value. This may (but does not - * necessarily) return an already-allocated instance. - * - * @param value the <code>int</code> value - * @return non-null; the appropriate instance - */ - public static CstInteger make(int value) { - /* - * Note: No need to synchronize, since we don't make any sort - * of guarantee about ==, and it's okay to overwrite existing - * entries too. - */ - int idx = (value & 0x7fffffff) % cache.length; - CstInteger obj = cache[idx]; - - if ((obj != null) && (obj.getValue() == value)) { - return obj; - } - - obj = new CstInteger(value); - cache[idx] = obj; - return obj; - } - - /** - * Constructs an instance. This constructor is private; use {@link #make}. - * - * @param value the <code>int</code> value - */ - private CstInteger(int value) { - super(value); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - int value = getIntBits(); - return "int{0x" + Hex.u4(value) + " / " + value + '}'; - } - - /** {@inheritDoc} */ - public Type getType() { - return Type.INT; - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "int"; - } - - /** {@inheritDoc} */ - public String toHuman() { - return Integer.toString(getIntBits()); - } - - /** - * Gets the <code>int</code> value. - * - * @return the value - */ - public int getValue() { - return getIntBits(); - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstInterfaceMethodRef.java b/dx/src/com/android/dx/rop/cst/CstInterfaceMethodRef.java deleted file mode 100644 index f169ec939..000000000 --- a/dx/src/com/android/dx/rop/cst/CstInterfaceMethodRef.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.cst; - -/** - * Constants of type <code>CONSTANT_InterfaceMethodref_info</code>. - */ -public final class CstInterfaceMethodRef - extends CstBaseMethodRef { - /** - * null-ok; normal {@link CstMethodRef} that corresponds to this - * instance, if calculated - */ - private CstMethodRef methodRef; - - /** - * Constructs an instance. - * - * @param definingClass non-null; the type of the defining class - * @param nat non-null; the name-and-type - */ - public CstInterfaceMethodRef(CstType definingClass, CstNat nat) { - super(definingClass, nat); - methodRef = null; - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "ifaceMethod"; - } - - /** - * Gets a normal (non-interface) {@link CstMethodRef} that corresponds to - * this instance. - * - * @return non-null; an appropriate instance - */ - public CstMethodRef toMethodRef() { - if (methodRef == null) { - methodRef = new CstMethodRef(getDefiningClass(), getNat()); - } - - return methodRef; - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstKnownNull.java b/dx/src/com/android/dx/rop/cst/CstKnownNull.java deleted file mode 100644 index 853e57e56..000000000 --- a/dx/src/com/android/dx/rop/cst/CstKnownNull.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.Type; - -/** - * Constant type to represent a known-<code>null</code> value. - */ -public final class CstKnownNull extends CstLiteralBits { - /** non-null; unique instance of this class */ - public static final CstKnownNull THE_ONE = new CstKnownNull(); - - /** - * Constructs an instance. This class is not publicly instantiable. Use - * {@link #THE_ONE}. - */ - private CstKnownNull() { - // This space intentionally left blank. - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - return (other instanceof CstKnownNull); - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - return 0x4466757a; - } - - /** {@inheritDoc} */ - @Override - protected int compareTo0(Constant other) { - return 0; - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return "known-null"; - } - - /** {@inheritDoc} */ - public Type getType() { - return Type.KNOWN_NULL; - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "known-null"; - } - - /** {@inheritDoc} */ - @Override - public boolean isCategory2() { - return false; - } - - /** {@inheritDoc} */ - public String toHuman() { - return "null"; - } - - /** {@inheritDoc} */ - @Override - public boolean fitsInInt() { - // See comment in getIntBits(). - return true; - } - - /** - * {@inheritDoc} - * - * As "literal bits," a known-null is always represented as the - * number zero. - */ - @Override - public int getIntBits() { - return 0; - } - - /** - * {@inheritDoc} - * - * As "literal bits," a known-null is always represented as the - * number zero. - */ - @Override - public long getLongBits() { - return 0; - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstLiteral32.java b/dx/src/com/android/dx/rop/cst/CstLiteral32.java deleted file mode 100644 index 31e96dd63..000000000 --- a/dx/src/com/android/dx/rop/cst/CstLiteral32.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.cst; - -/** - * Constants which are literal 32-bit values of some sort. - */ -public abstract class CstLiteral32 - extends CstLiteralBits { - /** the value as <code>int</code> bits */ - private final int bits; - - /** - * Constructs an instance. - * - * @param bits the value as <code>int</code> bits - */ - /*package*/ CstLiteral32(int bits) { - this.bits = bits; - } - - /** {@inheritDoc} */ - @Override - public final boolean equals(Object other) { - return (other != null) && - (getClass() == other.getClass()) && - bits == ((CstLiteral32) other).bits; - } - - /** {@inheritDoc} */ - @Override - public final int hashCode() { - return bits; - } - - /** {@inheritDoc} */ - @Override - protected int compareTo0(Constant other) { - int otherBits = ((CstLiteral32) other).bits; - - if (bits < otherBits) { - return -1; - } else if (bits > otherBits) { - return 1; - } else { - return 0; - } - } - - /** {@inheritDoc} */ - @Override - public final boolean isCategory2() { - return false; - } - - /** {@inheritDoc} */ - @Override - public final boolean fitsInInt() { - return true; - } - - /** {@inheritDoc} */ - @Override - public final int getIntBits() { - return bits; - } - - /** {@inheritDoc} */ - @Override - public final long getLongBits() { - return (long) bits; - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstLiteral64.java b/dx/src/com/android/dx/rop/cst/CstLiteral64.java deleted file mode 100644 index dd7d24dea..000000000 --- a/dx/src/com/android/dx/rop/cst/CstLiteral64.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.cst; - -/** - * Constants which are literal 64-bit values of some sort. - */ -public abstract class CstLiteral64 - extends CstLiteralBits { - /** the value as <code>long</code> bits */ - private final long bits; - - /** - * Constructs an instance. - * - * @param bits the value as <code>long</code> bits - */ - /*package*/ CstLiteral64(long bits) { - this.bits = bits; - } - - /** {@inheritDoc} */ - @Override - public final boolean equals(Object other) { - return (other != null) && - (getClass() == other.getClass()) && - bits == ((CstLiteral64) other).bits; - } - - /** {@inheritDoc} */ - @Override - public final int hashCode() { - return (int) bits ^ (int) (bits >> 32); - } - - /** {@inheritDoc} */ - @Override - protected int compareTo0(Constant other) { - long otherBits = ((CstLiteral64) other).bits; - - if (bits < otherBits) { - return -1; - } else if (bits > otherBits) { - return 1; - } else { - return 0; - } - } - - /** {@inheritDoc} */ - @Override - public final boolean isCategory2() { - return true; - } - - /** {@inheritDoc} */ - @Override - public final boolean fitsInInt() { - return (int) bits == bits; - } - - /** {@inheritDoc} */ - @Override - public final int getIntBits() { - return (int) bits; - } - - /** {@inheritDoc} */ - @Override - public final long getLongBits() { - return bits; - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstLiteralBits.java b/dx/src/com/android/dx/rop/cst/CstLiteralBits.java deleted file mode 100644 index 98a3f0e53..000000000 --- a/dx/src/com/android/dx/rop/cst/CstLiteralBits.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.cst; - -/** - * Constants which are literal bitwise values of some sort. - */ -public abstract class CstLiteralBits - extends TypedConstant { - /** - * Returns whether or not this instance's value may be accurately - * represented as an <code>int</code>. The rule is that if there - * is an <code>int</code> which may be sign-extended to yield this - * instance's value, then this method returns <code>true</code>. - * Otherwise, it returns <code>false</code>. - * - * @return <code>true</code> iff this instance fits in an <code>int</code> - */ - public abstract boolean fitsInInt(); - - /** - * Gets the value as <code>int</code> bits. If this instance contains - * more bits than fit in an <code>int</code>, then this returns only - * the low-order bits. - * - * @return the bits - */ - public abstract int getIntBits(); - - /** - * Gets the value as <code>long</code> bits. If this instance contains - * fewer bits than fit in a <code>long</code>, then the result of this - * method is the sign extension of the value. - * - * @return the bits - */ - public abstract long getLongBits(); - - /** - * Returns true if this value can fit in 16 bits with sign-extension. - * - * @return true if the sign-extended lower 16 bits are the same as - * the value. - */ - public boolean fitsIn16Bits() { - if (! fitsInInt()) { - return false; - } - - int bits = getIntBits(); - return (short) bits == bits; - } - - /** - * Returns true if this value can fit in 8 bits with sign-extension. - * - * @return true if the sign-extended lower 8 bits are the same as - * the value. - */ - public boolean fitsIn8Bits() { - if (! fitsInInt()) { - return false; - } - - int bits = getIntBits(); - return (byte) bits == bits; - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstLong.java b/dx/src/com/android/dx/rop/cst/CstLong.java deleted file mode 100644 index 377eb9312..000000000 --- a/dx/src/com/android/dx/rop/cst/CstLong.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.Type; -import com.android.dx.util.Hex; - -/** - * Constants of type <code>CONSTANT_Long_info</code>. - */ -public final class CstLong - extends CstLiteral64 { - /** non-null; instance representing <code>0</code> */ - public static final CstLong VALUE_0 = make(0); - - /** non-null; instance representing <code>1</code> */ - public static final CstLong VALUE_1 = make(1); - - /** - * Makes an instance for the given value. This may (but does not - * necessarily) return an already-allocated instance. - * - * @param value the <code>long</code> value - */ - public static CstLong make(long value) { - /* - * Note: Javadoc notwithstanding, this implementation always - * allocates. - */ - return new CstLong(value); - } - - /** - * Constructs an instance. This constructor is private; use {@link #make}. - * - * @param value the <code>long</code> value - */ - private CstLong(long value) { - super(value); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - long value = getLongBits(); - return "long{0x" + Hex.u8(value) + " / " + value + '}'; - } - - /** {@inheritDoc} */ - public Type getType() { - return Type.LONG; - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "long"; - } - - /** {@inheritDoc} */ - public String toHuman() { - return Long.toString(getLongBits()); - } - - /** - * Gets the <code>long</code> value. - * - * @return the value - */ - public long getValue() { - return getLongBits(); - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstMemberRef.java b/dx/src/com/android/dx/rop/cst/CstMemberRef.java deleted file mode 100644 index dbaad47eb..000000000 --- a/dx/src/com/android/dx/rop/cst/CstMemberRef.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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.cst; - -/** - * Constants of type <code>CONSTANT_*ref_info</code>. - */ -public abstract class CstMemberRef extends TypedConstant { - /** non-null; the type of the defining class */ - private final CstType definingClass; - - /** non-null; the name-and-type */ - private final CstNat nat; - - /** - * Constructs an instance. - * - * @param definingClass non-null; the type of the defining class - * @param nat non-null; the name-and-type - */ - /*package*/ CstMemberRef(CstType definingClass, CstNat nat) { - if (definingClass == null) { - throw new NullPointerException("definingClass == null"); - } - - if (nat == null) { - throw new NullPointerException("nat == null"); - } - - this.definingClass = definingClass; - this.nat = nat; - } - - /** {@inheritDoc} */ - @Override - public final boolean equals(Object other) { - if ((other == null) || (getClass() != other.getClass())) { - return false; - } - - CstMemberRef otherRef = (CstMemberRef) other; - return definingClass.equals(otherRef.definingClass) && - nat.equals(otherRef.nat); - } - - /** {@inheritDoc} */ - @Override - public final int hashCode() { - return (definingClass.hashCode() * 31) ^ nat.hashCode(); - } - - /** - * {@inheritDoc} - * - * <p><b>Note:</b> This implementation just compares the defining - * class and name, and it is up to subclasses to compare the rest - * after calling <code>super.compareTo0()</code>.</p> - */ - @Override - protected int compareTo0(Constant other) { - CstMemberRef otherMember = (CstMemberRef) other; - int cmp = definingClass.compareTo(otherMember.definingClass); - - if (cmp != 0) { - return cmp; - } - - CstUtf8 thisName = nat.getName(); - CstUtf8 otherName = otherMember.nat.getName(); - - return thisName.compareTo(otherName); - } - - /** {@inheritDoc} */ - @Override - public final String toString() { - return typeName() + '{' + toHuman() + '}'; - } - - /** {@inheritDoc} */ - @Override - public final boolean isCategory2() { - return false; - } - - /** {@inheritDoc} */ - public final String toHuman() { - return definingClass.toHuman() + '.' + nat.toHuman(); - } - - /** - * Gets the type of the defining class. - * - * @return non-null; the type of defining class - */ - public final CstType getDefiningClass() { - return definingClass; - } - - /** - * Gets the defining name-and-type. - * - * @return non-null; the name-and-type - */ - public final CstNat getNat() { - return nat; - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstMethodRef.java b/dx/src/com/android/dx/rop/cst/CstMethodRef.java deleted file mode 100644 index 766c9bfba..000000000 --- a/dx/src/com/android/dx/rop/cst/CstMethodRef.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.cst; - -/** - * Constants of type <code>CONSTANT_Methodref_info</code>. - */ -public final class CstMethodRef - extends CstBaseMethodRef { - /** - * Constructs an instance. - * - * @param definingClass non-null; the type of the defining class - * @param nat non-null; the name-and-type - */ - public CstMethodRef(CstType definingClass, CstNat nat) { - super(definingClass, nat); - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "method"; - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstNat.java b/dx/src/com/android/dx/rop/cst/CstNat.java deleted file mode 100644 index 106b599cc..000000000 --- a/dx/src/com/android/dx/rop/cst/CstNat.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.Type; - -/** - * Constants of type <code>CONSTANT_NameAndType_info</code>. - */ -public final class CstNat extends Constant { - /** - * non-null; the instance for name <code>TYPE</code> and descriptor - * <code>java.lang.Class</code>, which is useful when dealing with - * wrapped primitives - */ - public static final CstNat PRIMITIVE_TYPE_NAT = - new CstNat(new CstUtf8("TYPE"), - new CstUtf8("Ljava/lang/Class;")); - - /** non-null; the name */ - private final CstUtf8 name; - - /** non-null; the descriptor (type) */ - private final CstUtf8 descriptor; - - /** - * Constructs an instance. - * - * @param name non-null; the name - * @param descriptor non-null; the descriptor - */ - public CstNat(CstUtf8 name, CstUtf8 descriptor) { - if (name == null) { - throw new NullPointerException("name == null"); - } - - if (descriptor == null) { - throw new NullPointerException("descriptor == null"); - } - - this.name = name; - this.descriptor = descriptor; - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - if (!(other instanceof CstNat)) { - return false; - } - - CstNat otherNat = (CstNat) other; - return name.equals(otherNat.name) && - descriptor.equals(otherNat.descriptor); - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - return (name.hashCode() * 31) ^ descriptor.hashCode(); - } - - /** {@inheritDoc} */ - @Override - protected int compareTo0(Constant other) { - CstNat otherNat = (CstNat) other; - int cmp = name.compareTo(otherNat.name); - - if (cmp != 0) { - return cmp; - } - - return descriptor.compareTo(otherNat.descriptor); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return "nat{" + toHuman() + '}'; - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "nat"; - } - - /** {@inheritDoc} */ - @Override - public boolean isCategory2() { - return false; - } - - /** - * Gets the name. - * - * @return non-null; the name - */ - public CstUtf8 getName() { - return name; - } - - /** - * Gets the descriptor. - * - * @return non-null; the descriptor - */ - public CstUtf8 getDescriptor() { - return descriptor; - } - - /** - * Returns an unadorned but human-readable version of the name-and-type - * value. - * - * @return non-null; the human form - */ - public String toHuman() { - return name.toHuman() + ':' + descriptor.toHuman(); - } - - /** - * Gets the field type corresponding to this instance's descriptor. - * This method is only valid to call if the descriptor in fact describes - * a field (and not a method). - * - * @return non-null; the field type - */ - public Type getFieldType() { - return Type.intern(descriptor.getString()); - } - - /** - * Gets whether this instance has the name of a standard instance - * initialization method. This is just a convenient shorthand for - * <code>getName().getString().equals("<init>")</code>. - * - * @return <code>true</code> iff this is a reference to an - * instance initialization method - */ - public final boolean isInstanceInit() { - return name.getString().equals("<init>"); - } - - /** - * Gets whether this instance has the name of a standard class - * initialization method. This is just a convenient shorthand for - * <code>getName().getString().equals("<clinit>")</code>. - * - * @return <code>true</code> iff this is a reference to an - * instance initialization method - */ - public final boolean isClassInit() { - return name.getString().equals("<clinit>"); - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstShort.java b/dx/src/com/android/dx/rop/cst/CstShort.java deleted file mode 100644 index 38042541a..000000000 --- a/dx/src/com/android/dx/rop/cst/CstShort.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.Type; -import com.android.dx.util.Hex; - -/** - * Constants of type <code>short</code>. - */ -public final class CstShort - extends CstLiteral32 { - /** non-null; the value <code>0</code> as an instance of this class */ - public static final CstShort VALUE_0 = make((short) 0); - - /** - * Makes an instance for the given value. This may (but does not - * necessarily) return an already-allocated instance. - * - * @param value the <code>short</code> value - * @return non-null; the appropriate instance - */ - public static CstShort make(short value) { - return new CstShort(value); - } - - /** - * Makes an instance for the given <code>int</code> value. This - * may (but does not necessarily) return an already-allocated - * instance. - * - * @param value the value, which must be in range for a <code>short</code> - * @return non-null; the appropriate instance - */ - public static CstShort make(int value) { - short cast = (short) value; - - if (cast != value) { - throw new IllegalArgumentException("bogus short value: " + - value); - } - - return make(cast); - } - - /** - * Constructs an instance. This constructor is private; use {@link #make}. - * - * @param value the <code>short</code> value - */ - private CstShort(short value) { - super(value); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - int value = getIntBits(); - return "short{0x" + Hex.u2(value) + " / " + value + '}'; - } - - /** {@inheritDoc} */ - public Type getType() { - return Type.SHORT; - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "short"; - } - - /** {@inheritDoc} */ - public String toHuman() { - return Integer.toString(getIntBits()); - } - - /** - * Gets the <code>short</code> value. - * - * @return the value - */ - public short getValue() { - return (short) getIntBits(); - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstString.java b/dx/src/com/android/dx/rop/cst/CstString.java deleted file mode 100644 index 89a4c8bfe..000000000 --- a/dx/src/com/android/dx/rop/cst/CstString.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.Type; - -/** - * Constants of type <code>CONSTANT_String_info</code>. - */ -public final class CstString - extends TypedConstant { - /** non-null; the string value */ - private final CstUtf8 string; - - /** - * Constructs an instance. - * - * @param string non-null; the string value - */ - public CstString(CstUtf8 string) { - if (string == null) { - throw new NullPointerException("string == null"); - } - - this.string = string; - } - - /** - * Constructs an instance. - * - * @param string non-null; the string value - */ - public CstString(String string) { - this(new CstUtf8(string)); - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - if (!(other instanceof CstString)) { - return false; - } - - return string.equals(((CstString) other).string); - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - return string.hashCode(); - } - - /** {@inheritDoc} */ - @Override - protected int compareTo0(Constant other) { - return string.compareTo(((CstString) other).string); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return "string{" + toHuman() + '}'; - } - - /** {@inheritDoc} */ - public Type getType() { - return Type.STRING; - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "string"; - } - - /** {@inheritDoc} */ - @Override - public boolean isCategory2() { - return false; - } - - /** {@inheritDoc} */ - public String toHuman() { - return string.toQuoted(); - } - - /** - * Gets the string value. - * - * @return non-null; the string value - */ - public CstUtf8 getString() { - return string; - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstType.java b/dx/src/com/android/dx/rop/cst/CstType.java deleted file mode 100644 index 02df28d98..000000000 --- a/dx/src/com/android/dx/rop/cst/CstType.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.Type; - -import java.util.HashMap; - -/** - * Constants that represent an arbitrary type (reference or primitive). - */ -public final class CstType extends TypedConstant { - /** non-null; map of interned types */ - private static final HashMap<Type, CstType> interns = - new HashMap<Type, CstType>(100); - - /** non-null; instance corresponding to the class <code>Object</code> */ - public static final CstType OBJECT = intern(Type.OBJECT); - - /** non-null; instance corresponding to the class <code>Boolean</code> */ - public static final CstType BOOLEAN = intern(Type.BOOLEAN_CLASS); - - /** non-null; instance corresponding to the class <code>Byte</code> */ - public static final CstType BYTE = intern(Type.BYTE_CLASS); - - /** non-null; instance corresponding to the class <code>Character</code> */ - public static final CstType CHARACTER = intern(Type.CHARACTER_CLASS); - - /** non-null; instance corresponding to the class <code>Double</code> */ - public static final CstType DOUBLE = intern(Type.DOUBLE_CLASS); - - /** non-null; instance corresponding to the class <code>Float</code> */ - public static final CstType FLOAT = intern(Type.FLOAT_CLASS); - - /** non-null; instance corresponding to the class <code>Long</code> */ - public static final CstType LONG = intern(Type.LONG_CLASS); - - /** non-null; instance corresponding to the class <code>Integer</code> */ - public static final CstType INTEGER = intern(Type.INTEGER_CLASS); - - /** non-null; instance corresponding to the class <code>Short</code> */ - public static final CstType SHORT = intern(Type.SHORT_CLASS); - - /** non-null; instance corresponding to the class <code>Void</code> */ - public static final CstType VOID = intern(Type.VOID_CLASS); - - /** non-null; instance corresponding to the type <code>boolean[]</code> */ - public static final CstType BOOLEAN_ARRAY = intern(Type.BOOLEAN_ARRAY); - - /** non-null; instance corresponding to the type <code>byte[]</code> */ - public static final CstType BYTE_ARRAY = intern(Type.BYTE_ARRAY); - - /** non-null; instance corresponding to the type <code>char[]</code> */ - public static final CstType CHAR_ARRAY = intern(Type.CHAR_ARRAY); - - /** non-null; instance corresponding to the type <code>double[]</code> */ - public static final CstType DOUBLE_ARRAY = intern(Type.DOUBLE_ARRAY); - - /** non-null; instance corresponding to the type <code>float[]</code> */ - public static final CstType FLOAT_ARRAY = intern(Type.FLOAT_ARRAY); - - /** non-null; instance corresponding to the type <code>long[]</code> */ - public static final CstType LONG_ARRAY = intern(Type.LONG_ARRAY); - - /** non-null; instance corresponding to the type <code>int[]</code> */ - public static final CstType INT_ARRAY = intern(Type.INT_ARRAY); - - /** non-null; instance corresponding to the type <code>short[]</code> */ - public static final CstType SHORT_ARRAY = intern(Type.SHORT_ARRAY); - - /** non-null; the underlying type */ - private final Type type; - - /** - * null-ok; the type descriptor corresponding to this instance, if - * calculated - */ - private CstUtf8 descriptor; - - /** - * Returns an instance of this class that represents the wrapper - * class corresponding to a given primitive type. For example, if - * given {@link Type#INT}, this method returns the class reference - * <code>java.lang.Integer</code>. - * - * @param primitiveType non-null; the primitive type - * @return non-null; the corresponding wrapper class - */ - public static CstType forBoxedPrimitiveType(Type primitiveType) { - switch (primitiveType.getBasicType()) { - case Type.BT_BOOLEAN: return BOOLEAN; - case Type.BT_BYTE: return BYTE; - case Type.BT_CHAR: return CHARACTER; - case Type.BT_DOUBLE: return DOUBLE; - case Type.BT_FLOAT: return FLOAT; - case Type.BT_INT: return INTEGER; - case Type.BT_LONG: return LONG; - case Type.BT_SHORT: return SHORT; - case Type.BT_VOID: return VOID; - } - - throw new IllegalArgumentException("not primitive: " + primitiveType); - } - - /** - * Returns an interned instance of this class for the given type. - * - * @param type non-null; the underlying type - * @return non-null; an appropriately-constructed instance - */ - public static CstType intern(Type type) { - CstType cst = interns.get(type); - - if (cst == null) { - cst = new CstType(type); - interns.put(type, cst); - } - - return cst; - } - - /** - * Constructs an instance. - * - * @param type non-null; the underlying type - */ - public CstType(Type type) { - if (type == null) { - throw new NullPointerException("type == null"); - } - - if (type == type.KNOWN_NULL) { - throw new UnsupportedOperationException( - "KNOWN_NULL is not representable"); - } - - this.type = type; - this.descriptor = null; - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - if (!(other instanceof CstType)) { - return false; - } - - return type == ((CstType) other).type; - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - return type.hashCode(); - } - - /** {@inheritDoc} */ - @Override - protected int compareTo0(Constant other) { - String thisDescriptor = type.getDescriptor(); - String otherDescriptor = ((CstType) other).type.getDescriptor(); - return thisDescriptor.compareTo(otherDescriptor); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return "type{" + toHuman() + '}'; - } - - /** {@inheritDoc} */ - public Type getType() { - return Type.CLASS; - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "type"; - } - - /** {@inheritDoc} */ - @Override - public boolean isCategory2() { - return false; - } - - /** {@inheritDoc} */ - public String toHuman() { - return type.toHuman(); - } - - /** - * Gets the underlying type (as opposed to the type corresponding - * to this instance as a constant, which is always - * <code>Class</code>). - * - * @return non-null; the type corresponding to the name - */ - public Type getClassType() { - return type; - } - - /** - * Gets the type descriptor for this instance. - * - * @return non-null; the descriptor - */ - public CstUtf8 getDescriptor() { - if (descriptor == null) { - descriptor = new CstUtf8(type.getDescriptor()); - } - - return descriptor; - } -} diff --git a/dx/src/com/android/dx/rop/cst/CstUtf8.java b/dx/src/com/android/dx/rop/cst/CstUtf8.java deleted file mode 100644 index f0ca5f5b9..000000000 --- a/dx/src/com/android/dx/rop/cst/CstUtf8.java +++ /dev/null @@ -1,371 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.util.ByteArray; -import com.android.dx.util.Hex; - -/** - * Constants of type <code>CONSTANT_Utf8_info</code>. - */ -public final class CstUtf8 extends Constant { - /** - * non-null; instance representing <code>""</code>, that is, the - * empty string - */ - public static final CstUtf8 EMPTY_STRING = new CstUtf8(""); - - /** non-null; the UTF-8 value as a string */ - private final String string; - - /** non-null; the UTF-8 value as bytes */ - private final ByteArray bytes; - - /** - * Converts a string into its Java-style UTF-8 form. Java-style UTF-8 - * differs from normal UTF-8 in the handling of character '\0' and - * surrogate pairs. - * - * @param string non-null; the string to convert - * @return non-null; the UTF-8 bytes for it - */ - public static byte[] stringToUtf8Bytes(String string) { - int len = string.length(); - byte[] bytes = new byte[len * 3]; // Avoid having to reallocate. - int outAt = 0; - - for (int i = 0; i < len; i++) { - char c = string.charAt(i); - if ((c != 0) && (c < 0x80)) { - bytes[outAt] = (byte) c; - outAt++; - } else if (c < 0x800) { - bytes[outAt] = (byte) (((c >> 6) & 0x1f) | 0xc0); - bytes[outAt + 1] = (byte) ((c & 0x3f) | 0x80); - outAt += 2; - } else { - bytes[outAt] = (byte) (((c >> 12) & 0x0f) | 0xe0); - bytes[outAt + 1] = (byte) (((c >> 6) & 0x3f) | 0x80); - bytes[outAt + 2] = (byte) ((c & 0x3f) | 0x80); - outAt += 3; - } - } - - byte[] result = new byte[outAt]; - System.arraycopy(bytes, 0, result, 0, outAt); - return result; - } - - /** - * Converts an array of UTF-8 bytes into a string. - * - * @param bytes non-null; the bytes to convert - * @return non-null; the converted string - */ - public static String utf8BytesToString(ByteArray bytes) { - int length = bytes.size(); - char[] chars = new char[length]; // This is sized to avoid a realloc. - int outAt = 0; - - for (int at = 0; length > 0; /*at*/) { - int v0 = bytes.getUnsignedByte(at); - char out; - switch (v0 >> 4) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: { - // 0XXXXXXX -- single-byte encoding - length--; - if (v0 == 0) { - // A single zero byte is illegal. - return throwBadUtf8(v0, at); - } - out = (char) v0; - at++; - break; - } - case 0x0c: case 0x0d: { - // 110XXXXX -- two-byte encoding - length -= 2; - if (length < 0) { - return throwBadUtf8(v0, at); - } - int v1 = bytes.getUnsignedByte(at + 1); - if ((v1 & 0xc0) != 0x80) { - return throwBadUtf8(v1, at + 1); - } - int value = ((v0 & 0x1f) << 6) | (v1 & 0x3f); - if ((value != 0) && (value < 0x80)) { - /* - * This should have been represented with - * one-byte encoding. - */ - return throwBadUtf8(v1, at + 1); - } - out = (char) value; - at += 2; - break; - } - case 0x0e: { - // 1110XXXX -- three-byte encoding - length -= 3; - if (length < 0) { - return throwBadUtf8(v0, at); - } - int v1 = bytes.getUnsignedByte(at + 1); - if ((v1 & 0xc0) != 0x80) { - return throwBadUtf8(v1, at + 1); - } - int v2 = bytes.getUnsignedByte(at + 2); - if ((v1 & 0xc0) != 0x80) { - return throwBadUtf8(v2, at + 2); - } - int value = ((v0 & 0x0f) << 12) | ((v1 & 0x3f) << 6) | - (v2 & 0x3f); - if (value < 0x800) { - /* - * This should have been represented with one- or - * two-byte encoding. - */ - return throwBadUtf8(v2, at + 2); - } - out = (char) value; - at += 3; - break; - } - default: { - // 10XXXXXX, 1111XXXX -- illegal - return throwBadUtf8(v0, at); - } - } - chars[outAt] = out; - outAt++; - } - - return new String(chars, 0, outAt); - } - - /** - * Helper for {@link #utf8BytesToString}, which throws the right - * exception for a bogus utf-8 byte. - * - * @param value the byte value - * @param offset the file offset - * @return never - * @throws IllegalArgumentException always thrown - */ - private static String throwBadUtf8(int value, int offset) { - throw new IllegalArgumentException("bad utf-8 byte " + Hex.u1(value) + - " at offset " + Hex.u4(offset)); - } - - /** - * Constructs an instance from a <code>String</code>. - * - * @param string non-null; the UTF-8 value as a string - */ - public CstUtf8(String string) { - if (string == null) { - throw new NullPointerException("string == null"); - } - - this.string = string.intern(); - this.bytes = new ByteArray(stringToUtf8Bytes(string)); - } - - /** - * Constructs an instance from some UTF-8 bytes. - * - * @param bytes non-null; array of the UTF-8 bytes - */ - public CstUtf8(ByteArray bytes) { - if (bytes == null) { - throw new NullPointerException("bytes == null"); - } - - this.bytes = bytes; - this.string = utf8BytesToString(bytes).intern(); - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - if (!(other instanceof CstUtf8)) { - return false; - } - - return string.equals(((CstUtf8) other).string); - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - return string.hashCode(); - } - - /** {@inheritDoc} */ - @Override - protected int compareTo0(Constant other) { - return string.compareTo(((CstUtf8) other).string); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return "utf8{\"" + toHuman() + "\"}"; - } - - /** {@inheritDoc} */ - @Override - public String typeName() { - return "utf8"; - } - - /** {@inheritDoc} */ - @Override - public boolean isCategory2() { - return false; - } - - /** {@inheritDoc} */ - public String toHuman() { - int len = string.length(); - StringBuilder sb = new StringBuilder(len * 3 / 2); - - for (int i = 0; i < len; i++) { - char c = string.charAt(i); - if ((c >= ' ') && (c < 0x7f)) { - if ((c == '\'') || (c == '\"') || (c == '\\')) { - sb.append('\\'); - } - sb.append(c); - } else if (c <= 0x7f) { - switch (c) { - case '\n': sb.append("\\n"); break; - case '\r': sb.append("\\r"); break; - case '\t': sb.append("\\t"); break; - default: { - /* - * Represent the character as an octal escape. - * If the next character is a valid octal - * digit, disambiguate by using the - * three-digit form. - */ - char nextChar = - (i < (len - 1)) ? string.charAt(i + 1) : 0; - boolean displayZero = - (nextChar >= '0') && (nextChar <= '7'); - sb.append('\\'); - for (int shift = 6; shift >= 0; shift -= 3) { - char outChar = (char) (((c >> shift) & 7) + '0'); - if ((outChar != '0') || displayZero) { - sb.append(outChar); - displayZero = true; - } - } - if (! displayZero) { - // Ironic edge case: The original value was 0. - sb.append('0'); - } - break; - } - } - } else { - sb.append("\\u"); - sb.append(Character.forDigit(c >> 12, 16)); - sb.append(Character.forDigit((c >> 8) & 0x0f, 16)); - sb.append(Character.forDigit((c >> 4) & 0x0f, 16)); - sb.append(Character.forDigit(c & 0x0f, 16)); - } - } - - return sb.toString(); - } - - /** - * Gets the value as a human-oriented string, surrounded by double - * quotes. - * - * @return non-null; the quoted string - */ - public String toQuoted() { - return '\"' + toHuman() + '\"'; - } - - /** - * Gets the value as a human-oriented string, surrounded by double - * quotes, but ellipsizes the result if it is longer than the given - * maximum length - * - * @param maxLength >= 5; the maximum length of the string to return - * @return non-null; the quoted string - */ - public String toQuoted(int maxLength) { - String string = toHuman(); - int length = string.length(); - String ellipses; - - if (length <= (maxLength - 2)) { - ellipses = ""; - } else { - string = string.substring(0, maxLength - 5); - ellipses = "..."; - } - - return '\"' + string + ellipses + '\"'; - } - - /** - * Gets the UTF-8 value as a string. - * The returned string is always already interned. - * - * @return non-null; the UTF-8 value as a string - */ - public String getString() { - return string; - } - - /** - * Gets the UTF-8 value as UTF-8 encoded bytes. - * - * @return non-null; an array of the UTF-8 bytes - */ - public ByteArray getBytes() { - return bytes; - } - - /** - * Gets the size of this instance as UTF-8 code points. That is, - * get the number of bytes in the UTF-8 encoding of this instance. - * - * @return >= 0; the UTF-8 size - */ - public int getUtf8Size() { - return bytes.size(); - } - - /** - * Gets the size of this instance as UTF-16 code points. That is, - * get the number of 16-bit chars in the UTF-16 encoding of this - * instance. This is the same as the <code>length</code> of the - * Java <code>String</code> representation of this instance. - * - * @return >= 0; the UTF-16 size - */ - public int getUtf16Size() { - return string.length(); - } -} diff --git a/dx/src/com/android/dx/rop/cst/StdConstantPool.java b/dx/src/com/android/dx/rop/cst/StdConstantPool.java deleted file mode 100644 index 69791020f..000000000 --- a/dx/src/com/android/dx/rop/cst/StdConstantPool.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.util.ExceptionWithContext; -import com.android.dx.util.Hex; -import com.android.dx.util.MutabilityControl; - -/** - * Standard implementation of {@link ConstantPool}, which directly stores - * an array of {@link Constant} objects and can be made immutable. - */ -public final class StdConstantPool - extends MutabilityControl implements ConstantPool { - /** non-null; array of entries */ - private final Constant[] entries; - - /** - * Constructs an instance. All indices initially contain <code>null</code>. - * - * @param size the size of the pool; this corresponds to the - * class file field <code>constant_pool_count</code>, and is in fact - * always at least one more than the actual size of the constant pool, - * as element <code>0</code> is always invalid. - */ - public StdConstantPool(int size) { - super(size > 1); - - if (size < 1) { - throw new IllegalArgumentException("size < 1"); - } - - entries = new Constant[size]; - } - - /** {@inheritDoc} */ - public int size() { - return entries.length; - } - - /** {@inheritDoc} */ - public Constant getOrNull(int n) { - try { - return entries[n]; - } catch (IndexOutOfBoundsException ex) { - // Translate the exception. - return throwInvalid(n); - } - } - - /** {@inheritDoc} */ - public Constant get0Ok(int n) { - if (n == 0) { - return null; - } - - return get(n); - } - - /** {@inheritDoc} */ - public Constant get(int n) { - try { - Constant result = entries[n]; - - if (result == null) { - throwInvalid(n); - } - - return result; - } catch (IndexOutOfBoundsException ex) { - // Translate the exception. - return throwInvalid(n); - } - } - - /** - * Sets the entry at the given index. - * - * @param n >= 1, < size(); which entry - * @param cst null-ok; the constant to store - */ - public void set(int n, Constant cst) { - throwIfImmutable(); - - boolean cat2 = (cst != null) && cst.isCategory2(); - - if (n < 1) { - throw new IllegalArgumentException("n < 1"); - } - - if (cat2) { - // Storing a category-2 entry nulls out the next index. - if (n == (entries.length - 1)) { - throw new IllegalArgumentException("(n == size - 1) && " + - "cst.isCategory2()"); - } - entries[n + 1] = null; - } - - if ((cst != null) && (entries[n] == null)) { - /* - * Overwriting the second half of a category-2 entry nulls out - * the first half. - */ - Constant prev = entries[n - 1]; - if ((prev != null) && prev.isCategory2()) { - entries[n - 1] = null; - } - } - - entries[n] = cst; - } - - /** - * Throws the right exception for an invalid cpi. - * - * @param idx the bad cpi - * @return never - * @throws ExceptionWithContext always thrown - */ - private static Constant throwInvalid(int idx) { - throw new ExceptionWithContext("invalid constant pool index " + - Hex.u2(idx)); - } -} diff --git a/dx/src/com/android/dx/rop/cst/TypedConstant.java b/dx/src/com/android/dx/rop/cst/TypedConstant.java deleted file mode 100644 index 54472b058..000000000 --- a/dx/src/com/android/dx/rop/cst/TypedConstant.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.cst; - -import com.android.dx.rop.type.TypeBearer; - -/** - * Base class for constants which implement {@link TypeBearer}. - */ -public abstract class TypedConstant - extends Constant implements TypeBearer { - /** - * {@inheritDoc} - * - * This implentation always returns <code>this</code>. - */ - public final TypeBearer getFrameType() { - return this; - } - - /** {@inheritDoc} */ - public final int getBasicType() { - return getType().getBasicType(); - } - - /** {@inheritDoc} */ - public final int getBasicFrameType() { - return getType().getBasicFrameType(); - } - - /** {@inheritDoc} */ - public final boolean isConstant() { - return true; - } -} diff --git a/dx/src/com/android/dx/rop/cst/Zeroes.java b/dx/src/com/android/dx/rop/cst/Zeroes.java deleted file mode 100644 index 3379b6cc4..000000000 --- a/dx/src/com/android/dx/rop/cst/Zeroes.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2008 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.cst; - -import com.android.dx.rop.type.Type; - -/** - * Utility for turning types into zeroes. - */ -public final class Zeroes { - /** - * This class is uninstantiable. - */ - private Zeroes() { - // This space intentionally left blank. - } - - /** - * Gets the "zero" (or <code>null</code>) value for the given type. - * - * @param type non-null; the type in question - * @return non-null; its "zero" value - */ - public static Constant zeroFor(Type type) { - switch (type.getBasicType()) { - case Type.BT_BOOLEAN: return CstBoolean.VALUE_FALSE; - case Type.BT_BYTE: return CstByte.VALUE_0; - case Type.BT_CHAR: return CstChar.VALUE_0; - case Type.BT_DOUBLE: return CstDouble.VALUE_0; - case Type.BT_FLOAT: return CstFloat.VALUE_0; - case Type.BT_INT: return CstInteger.VALUE_0; - case Type.BT_LONG: return CstLong.VALUE_0; - case Type.BT_SHORT: return CstShort.VALUE_0; - case Type.BT_OBJECT: return CstKnownNull.THE_ONE; - default: { - throw new UnsupportedOperationException("no zero for type: " + - type.toHuman()); - } - } - } -} diff --git a/dx/src/com/android/dx/rop/cst/package.html b/dx/src/com/android/dx/rop/cst/package.html deleted file mode 100644 index c784d163d..000000000 --- a/dx/src/com/android/dx/rop/cst/package.html +++ /dev/null @@ -1,9 +0,0 @@ -<body> -<p>Interfaces and implementation of things related to the constant pool.</p> - -<p><b>PACKAGES USED:</b> -<ul> -<li><code>com.android.dx.rop.type</code></li> -<li><code>com.android.dx.util</code></li> -</ul> -</body> diff --git a/dx/src/com/android/dx/rop/package-info.java b/dx/src/com/android/dx/rop/package-info.java deleted file mode 100644 index 97fe9de73..000000000 --- a/dx/src/com/android/dx/rop/package-info.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2008 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; - -/** - * <h1>An Introduction to Rop Form</h1> - * - * This package contains classes associated with dx's <code>Rop</code> - * intermediate form.<p> - * - * The Rop form is intended to represent the instructions and the control-flow - * graph in a reasonably programmatically useful form while closely mirroring - * the dex instruction set.<p> - * - * <h2>Key Classes</h2> - * - * <ul> - * <li> {@link RopMethod}, the representation of an individual method - * <li> {@link BasicBlock} and its per-method container, {@link BasicBlockList}, - * the representation of control flow elements. - * <li> {@link Insn} and its subclasses along with its per-basic block - * container {@link InsnList}. <code>Insn</code> instances represent - * individual instructions in the abstract register machine. - * <li> {@link RegisterSpec} and its container {@link RegisterSpecList}. A - * register spec encodes register number, register width, type information, - * and potentially local variable information as well for instruction sources - * and results. - * <li> {@link Rop} instances represent opcodes in the abstract machine. Many - * <code>Rop</code> instances are singletons defined in static fields in - * {@link Rops}. The rest are constructed dynamically using static methods - * in <code>Rops</code> - * <li> {@link RegOps} lists numeric constants for the opcodes - * <li> {@link Constant} and its subclasses represent constant data values - * that opcodes may refer to. - * <li> {@link Type} instances represent the core data types that can be - * handled by the abstract machine. - * <li> The {@link TypeBearer} interface is implemented by classes that - * represent a core data type, but may also have secondary information - * (such as constant value) associated with them. - * <ul> - * - * <h2>Control-Flow Graph</h2> - * - * Each method is separated into a list of basic blocks. For the most part, - * basic blocks are referred to by a positive integer - * {@link BasicBlock#getLabel label}, which is always unique per method. The - * label value is typically derived from a bytecode address from the source - * bytecode. Blocks that don't originate directly from source bytecode have - * labels generated for them in a mostly arbitrary order.<p> - * - * Blocks are referred to by their label, for the most part, because <code> - * BasicBlock</code> instances are immutable and thus any modification to - * the control flow graph or the instruction list results in replacement - * instances (with identical labels) being created.<p> - * - * A method has a single {@link RopMethod#getFirstLabel entry block} and 0 - * to N {@link RopMethod#getExitPredecessors exit predecessor blocks} which - * will return. All blocks that are not the entry block will have at least - * one predecessor (or are unreachable and should be removed from the block - * list). All blocks that are not exit predecessors must have at least one - * successor.<p> - * - * Since all blocks must branch, all blocks must have, as their final - * instruction, an instruction whose opcode has a {@link Rop#getBranchingness - * branchingness} other than {@link Rop.BRANCH_NONE}. Furthermore, branching - * instructions may only be the final instruction in any basic block. If - * no other terminating opcode is appropriate, use a {@link Rops#GOTO GOTO}.<p> - * - * Typically a block will have a {@link BasicBlock#getPrimarySuccessor - * primary successor} which distinguishes a particular control flow path. - * For {Rops#isCallLike}call or call-like} opcodes, this is the path taken - * in the non-exceptional case, where all other successors represent - * various exception paths. For comparison operators such as - * {@link Rops#IF_EQZ_INT}, the primary successor represents the path taken - * if the <b>condition evaluates to false</b>. For {@link SwitchInsn switch - * instructions}, the primary successor is the default case.<p> - * - * A basic block's successor list is ordered and may refer to unique labels - * multiple times. For example, if a switch statement contains multiple case - * statements for the same code path, a single basic block will likely - * appear in the successor list multiple times. In general, the - * significance of the successor list's order (like the significance of - * the primary successor) is a property of the final instruction of the basic - * block. A basic block containing a {@link ThrowingInsn}, for example, has - * its successor list in an order identical to the - * {@link ThrowingInsn#getCatches} instruction's catches list, with the - * primary successor (the no-exception case) listed at the end. - * - * It is legal for a basic block to have no primary successor. An obvious - * example of this is a block that terminates in a {@link Rops#THROW throw} - * instruction where a catch block exists inside the current method for that - * exception class. Since the only possible path is the exception path, only - * the exception path (which cannot be a primary successor) is a successor. - * An example of this is shown in <code>dx/tests/092-ssa-cfg-edge-cases</code>. - * - * <h2>Rop Instructions</h2> - * - * <h3>move-result and move-result-pseudo</h3> - * - * An instruction that may throw an exception may not specify a result. This - * is necessary because the result register will not be assigned to if an - * exception occurs while processing said instruction and a result assignment - * may not occur. Since result assignments only occur in the non-exceptional - * case, the result assignments for throwing instructions can be said to occur - * at the beginning of the primary successor block rather than at the end of - * the current block. The Rop form represents the result assignments this way. - * Throwing instructions may not directly specify results. Instead, result - * assignments are represented by {@link - * Rops#MOVE_RESULT move-result} or {@link Rops#MOVE_RESULT_PSEUDO - * move-result-pseudo} instructions at the top of the primary successor block. - * - * Only a single <code>move-result</code> or <code>move-result-pseudo</code> - * may exist in any block and it must be exactly the first instruction in the - * block. - * - * A <code>move-result</code> instruction is used for the results of call-like - * instructions. If the value produced by a <code>move-result</code> is not - * used by the method, it may be eliminated as dead code. - * - * A <code>move-result-pseudo</code> instruction is used for the results of - * non-call-like throwing instructions. It may never be considered dead code - * since the final dex instruction will always indicate a result register. - * If a required <code>move-result-pseudo</code> instruction is not found - * during conversion to dex bytecode, an exception will be thrown. - * - * <h3>move-exception</h3> - * - * A {@link RegOps.MOVE_EXCEPTION move-exception} instruction may appear at - * the start of a catch block, and represents the obtaining of the thrown - * exception instance. It may only occur as the first instruction in a - * basic block, and any basic block in which it occurs must be reachable only - * as an exception successor. - * - * <h3>move-param</h3> - * - * A {@link RegOps.MOVE_PARAM move-param} instruction represents a method - * parameter. Every <code>move-param</code> instruction is a - * {@link PlainCstInsn}. The index of the method parameter they refer to is - * carried as the {@link CstInteger integer constant} associated with the - * instruction. - * - * Any number of <code>move-param</code> instructions referring to the same - * parameter index may be included in a method's instruction lists. They - * have no restrictions on placement beyond those of any other - * {@link Rop.BRANCH_NONE} instruction. Note that the SSA optimizer arranges the - * parameter assignments to align with the dex bytecode calling conventions. - * With parameter assignments so arranged, the - * {@link com.android.dx.dex.code.RopTranslator} sees Rop <code>move-param</code> - * instructions as unnecessary in dex form and eliminates them. - * - * <h3>mark-local</h3> - * - * A {@link RegOps.MARK_LOCAL mark-local} instruction indicates that a local - * variable becomes live in a specified register specified register for the - * purposes of debug information. A <code>mark-local</code> instruction has - * a single source (the register which will now be considered a local variable) - * and no results. The instruction has no side effect.<p> - * - * In a typical case, a local variable's lifetime begins with an - * assignment. The local variable whose information is present in a result's - * {@link RegisterSpec#getLocalItem LocalItem} is considered to begin (or move - * between registers) when the instruction is executed.<p> - * - * However, sometimes a local variable can begin its life or move without - * an assignment occurring. A common example of this is occurs in the Rop - * representation of the following code:<p> - * - * <code> - * try { - * Object foo = null; - * foo = new Object(); - * } catch (Throwable ex) { - * } - * </code> - * - * An object's initialization occurs in two steps. First, a <code>new-instance - * </code> instruction is executed, whose result is stored in a register. - * However, that register can not yet be considered to contain "foo". That's - * because the instance's constructor method must be called via an - * <code>invoke</code> instruction. The constructor method, however, may - * throw an exception. And if an exception occurs, then "foo" should remain - * null. So "foo" becomes the value of the result of the <code>new-instance - * </code> instruction after the (void) constructor method is invoked and - * returns successfully. In such a case, a <code>mark-local</code> will - * typically occur at the beginning of the primary successor block following - * the invocation to the constructor. - */ diff --git a/dx/src/com/android/dx/rop/type/Prototype.java b/dx/src/com/android/dx/rop/type/Prototype.java deleted file mode 100644 index a6ee74252..000000000 --- a/dx/src/com/android/dx/rop/type/Prototype.java +++ /dev/null @@ -1,397 +0,0 @@ -/* - * 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.type; - -import java.util.HashMap; - -/** - * Representation of a method decriptor. Instances of this class are - * generally interned and may be usefully compared with each other - * using <code>==</code>. - */ -public final class Prototype implements Comparable<Prototype> { - /** non-null; intern table mapping string descriptors to instances */ - private static final HashMap<String, Prototype> internTable = - new HashMap<String, Prototype>(500); - - /** non-null; method descriptor */ - private final String descriptor; - - /** non-null; return type */ - private final Type returnType; - - /** non-null; list of parameter types */ - private final StdTypeList parameterTypes; - - /** null-ok; list of parameter frame types, if calculated */ - private StdTypeList parameterFrameTypes; - - /** - * Returns the unique instance corresponding to the - * given method descriptor. See vmspec-2 sec4.3.3 for details on the - * field descriptor syntax. - * - * @param descriptor non-null; the descriptor - * @return non-null; the corresponding instance - * @throws IllegalArgumentException thrown if the descriptor has - * invalid syntax - */ - public static Prototype intern(String descriptor) { - if (descriptor == null) { - throw new NullPointerException("descriptor == null"); - } - - Prototype result = internTable.get(descriptor); - if (result != null) { - return result; - } - - Type[] params = makeParameterArray(descriptor); - int paramCount = 0; - int at = 1; - - for (;;) { - int startAt = at; - char c = descriptor.charAt(at); - if (c == ')') { - at++; - break; - } - - // Skip array markers. - while (c == '[') { - at++; - c = descriptor.charAt(at); - } - - if (c == 'L') { - // It looks like the start of a class name; find the end. - int endAt = descriptor.indexOf(';', at); - if (endAt == -1) { - throw new IllegalArgumentException("bad descriptor"); - } - at = endAt + 1; - } else { - at++; - } - - params[paramCount] = - Type.intern(descriptor.substring(startAt, at)); - paramCount++; - } - - Type returnType = Type.internReturnType(descriptor.substring(at)); - StdTypeList parameterTypes = new StdTypeList(paramCount); - - for (int i = 0; i < paramCount; i++) { - parameterTypes.set(i, params[i]); - } - - result = new Prototype(descriptor, returnType, parameterTypes); - return putIntern(result); - } - - /** - * Helper for {@link #intern} which returns an empty array to - * populate with parsed parameter types, and which also ensures - * that there is a '(' at the start of the descriptor and a - * single ')' somewhere before the end. - * - * @param descriptor non-null; the descriptor string - * @return non-null; array large enough to hold all parsed parameter - * types, but which is likely actually larger than needed - */ - private static Type[] makeParameterArray(String descriptor) { - int length = descriptor.length(); - - if (descriptor.charAt(0) != '(') { - throw new IllegalArgumentException("bad descriptor"); - } - - /* - * This is a cheesy way to establish an upper bound on the - * number of parameters: Just count capital letters. - */ - int closeAt = 0; - int maxParams = 0; - for (int i = 1; i < length; i++) { - char c = descriptor.charAt(i); - if (c == ')') { - closeAt = i; - break; - } - if ((c >= 'A') && (c <= 'Z')) { - maxParams++; - } - } - - if ((closeAt == 0) || (closeAt == (length - 1))) { - throw new IllegalArgumentException("bad descriptor"); - } - - if (descriptor.indexOf(')', closeAt + 1) != -1) { - throw new IllegalArgumentException("bad descriptor"); - } - - return new Type[maxParams]; - } - - /** - * Interns an instance, adding to the descriptor as necessary based - * on the given definer, name, and flags. For example, an init - * method has an uninitialized object of type <code>definer</code> - * as its first argument. - * - * @param descriptor non-null; the descriptor string - * @param definer non-null; class the method is defined on - * @param isStatic whether this is a static method - * @param isInit whether this is an init method - * @return non-null; the interned instance - */ - public static Prototype intern(String descriptor, Type definer, - boolean isStatic, boolean isInit) { - Prototype base = intern(descriptor); - - if (isStatic) { - return base; - } - - if (isInit) { - definer = definer.asUninitialized(Integer.MAX_VALUE); - } - - return base.withFirstParameter(definer); - } - - /** - * Interns an instance which consists of the given number of - * <code>int</code>s along with the given return type - * - * @param returnType non-null; the return type - * @param count > 0; the number of elements in the prototype - * @return non-null; the interned instance - */ - public static Prototype internInts(Type returnType, int count) { - // Make the descriptor... - - StringBuffer sb = new StringBuffer(100); - - sb.append('('); - - for (int i = 0; i < count; i++) { - sb.append('I'); - } - - sb.append(')'); - sb.append(returnType.getDescriptor()); - - // ...and intern it. - return intern(sb.toString()); - } - - /** - * Constructs an instance. This is a private constructor; use one - * of the public static methods to get instances. - * - * @param descriptor non-null; the descriptor string - */ - private Prototype(String descriptor, Type returnType, - StdTypeList parameterTypes) { - if (descriptor == null) { - throw new NullPointerException("descriptor == null"); - } - - if (returnType == null) { - throw new NullPointerException("returnType == null"); - } - - if (parameterTypes == null) { - throw new NullPointerException("parameterTypes == null"); - } - - this.descriptor = descriptor; - this.returnType = returnType; - this.parameterTypes = parameterTypes; - this.parameterFrameTypes = null; - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - if (this == other) { - /* - * Since externally-visible instances are interned, this - * check helps weed out some easy cases. - */ - return true; - } - - if (!(other instanceof Prototype)) { - return false; - } - - return descriptor.equals(((Prototype) other).descriptor); - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - return descriptor.hashCode(); - } - - /** {@inheritDoc} */ - public int compareTo(Prototype other) { - if (this == other) { - return 0; - } - - /* - * The return type is the major order, and then args in order, - * and then the shorter list comes first (similar to string - * sorting). - */ - - int result = returnType.compareTo(other.returnType); - - if (result != 0) { - return result; - } - - int thisSize = parameterTypes.size(); - int otherSize = other.parameterTypes.size(); - int size = Math.min(thisSize, otherSize); - - for (int i = 0; i < size; i++) { - Type thisType = parameterTypes.get(i); - Type otherType = other.parameterTypes.get(i); - - result = thisType.compareTo(otherType); - - if (result != 0) { - return result; - } - } - - if (thisSize < otherSize) { - return -1; - } else if (thisSize > otherSize) { - return 1; - } else { - return 0; - } - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return descriptor; - } - - /** - * Gets the descriptor string. - * - * @return non-null; the descriptor - */ - public String getDescriptor() { - return descriptor; - } - - /** - * Gets the return type. - * - * @return non-null; the return type - */ - public Type getReturnType() { - return returnType; - } - - /** - * Gets the list of parameter types. - * - * @return non-null; the list of parameter types - */ - public StdTypeList getParameterTypes() { - return parameterTypes; - } - - /** - * Gets the list of frame types corresponding to the list of parameter - * types. The difference between the two lists (if any) is that all - * "intlike" types (see {@link Type#isIntlike}) are replaced by - * {@link Type#INT}. - * - * @return non-null; the list of parameter frame types - */ - public StdTypeList getParameterFrameTypes() { - if (parameterFrameTypes == null) { - int sz = parameterTypes.size(); - StdTypeList list = new StdTypeList(sz); - boolean any = false; - for (int i = 0; i < sz; i++) { - Type one = parameterTypes.get(i); - if (one.isIntlike()) { - any = true; - one = Type.INT; - } - list.set(i, one); - } - parameterFrameTypes = any ? list : parameterTypes; - } - - return parameterFrameTypes; - } - - /** - * Returns a new interned instance, which is the same as this instance, - * except that it has an additional parameter prepended to the original's - * argument list. - * - * @param param non-null; the new first parameter - * @return non-null; an appropriately-constructed instance - */ - public Prototype withFirstParameter(Type param) { - String newDesc = "(" + param.getDescriptor() + descriptor.substring(1); - StdTypeList newParams = parameterTypes.withFirst(param); - - newParams.setImmutable(); - - Prototype result = - new Prototype(newDesc, returnType, newParams); - - return putIntern(result); - } - - /** - * Puts the given instance in the intern table if it's not already - * there. If a conflicting value is already in the table, then leave it. - * Return the interned value. - * - * @param desc non-null; instance to make interned - * @return non-null; the actual interned object - */ - private static Prototype putIntern(Prototype desc) { - synchronized (internTable) { - String descriptor = desc.getDescriptor(); - Prototype already = internTable.get(descriptor); - if (already != null) { - return already; - } - internTable.put(descriptor, desc); - return desc; - } - } -} diff --git a/dx/src/com/android/dx/rop/type/StdTypeList.java b/dx/src/com/android/dx/rop/type/StdTypeList.java deleted file mode 100644 index a4c2d44b0..000000000 --- a/dx/src/com/android/dx/rop/type/StdTypeList.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * 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.type; - -import com.android.dx.util.FixedSizeList; - -/** - * Standard implementation of {@link TypeList}. - */ -public final class StdTypeList - extends FixedSizeList implements TypeList { - /** non-null; no-element instance */ - public static final StdTypeList EMPTY = new StdTypeList(0); - - /** non-null; the list <code>[int]</code> */ - public static final StdTypeList INT = StdTypeList.make(Type.INT); - - /** non-null; the list <code>[long]</code> */ - public static final StdTypeList LONG = StdTypeList.make(Type.LONG); - - /** non-null; the list <code>[float]</code> */ - public static final StdTypeList FLOAT = StdTypeList.make(Type.FLOAT); - - /** non-null; the list <code>[double]</code> */ - public static final StdTypeList DOUBLE = StdTypeList.make(Type.DOUBLE); - - /** non-null; the list <code>[Object]</code> */ - public static final StdTypeList OBJECT = StdTypeList.make(Type.OBJECT); - - /** non-null; the list <code>[ReturnAddress]</code> */ - public static final StdTypeList RETURN_ADDRESS - = StdTypeList.make(Type.RETURN_ADDRESS); - - /** non-null; the list <code>[Throwable]</code> */ - public static final StdTypeList THROWABLE = - StdTypeList.make(Type.THROWABLE); - - /** non-null; the list <code>[int, int]</code> */ - public static final StdTypeList INT_INT = - StdTypeList.make(Type.INT, Type.INT); - - /** non-null; the list <code>[long, long]</code> */ - public static final StdTypeList LONG_LONG = - StdTypeList.make(Type.LONG, Type.LONG); - - /** non-null; the list <code>[float, float]</code> */ - public static final StdTypeList FLOAT_FLOAT = - StdTypeList.make(Type.FLOAT, Type.FLOAT); - - /** non-null; the list <code>[double, double]</code> */ - public static final StdTypeList DOUBLE_DOUBLE = - StdTypeList.make(Type.DOUBLE, Type.DOUBLE); - - /** non-null; the list <code>[Object, Object]</code> */ - public static final StdTypeList OBJECT_OBJECT = - StdTypeList.make(Type.OBJECT, Type.OBJECT); - - /** non-null; the list <code>[int, Object]</code> */ - public static final StdTypeList INT_OBJECT = - StdTypeList.make(Type.INT, Type.OBJECT); - - /** non-null; the list <code>[long, Object]</code> */ - public static final StdTypeList LONG_OBJECT = - StdTypeList.make(Type.LONG, Type.OBJECT); - - /** non-null; the list <code>[float, Object]</code> */ - public static final StdTypeList FLOAT_OBJECT = - StdTypeList.make(Type.FLOAT, Type.OBJECT); - - /** non-null; the list <code>[double, Object]</code> */ - public static final StdTypeList DOUBLE_OBJECT = - StdTypeList.make(Type.DOUBLE, Type.OBJECT); - - /** non-null; the list <code>[long, int]</code> */ - public static final StdTypeList LONG_INT = - StdTypeList.make(Type.LONG, Type.INT); - - /** non-null; the list <code>[int[], int]</code> */ - public static final StdTypeList INTARR_INT = - StdTypeList.make(Type.INT_ARRAY, Type.INT); - - /** non-null; the list <code>[long[], int]</code> */ - public static final StdTypeList LONGARR_INT = - StdTypeList.make(Type.LONG_ARRAY, Type.INT); - - /** non-null; the list <code>[float[], int]</code> */ - public static final StdTypeList FLOATARR_INT = - StdTypeList.make(Type.FLOAT_ARRAY, Type.INT); - - /** non-null; the list <code>[double[], int]</code> */ - public static final StdTypeList DOUBLEARR_INT = - StdTypeList.make(Type.DOUBLE_ARRAY, Type.INT); - - /** non-null; the list <code>[Object[], int]</code> */ - public static final StdTypeList OBJECTARR_INT = - StdTypeList.make(Type.OBJECT_ARRAY, Type.INT); - - /** non-null; the list <code>[boolean[], int]</code> */ - public static final StdTypeList BOOLEANARR_INT = - StdTypeList.make(Type.BOOLEAN_ARRAY, Type.INT); - - /** non-null; the list <code>[byte[], int]</code> */ - public static final StdTypeList BYTEARR_INT = - StdTypeList.make(Type.BYTE_ARRAY, Type.INT); - - /** non-null; the list <code>[char[], int]</code> */ - public static final StdTypeList CHARARR_INT = - StdTypeList.make(Type.CHAR_ARRAY, Type.INT); - - /** non-null; the list <code>[short[], int]</code> */ - public static final StdTypeList SHORTARR_INT = - StdTypeList.make(Type.SHORT_ARRAY, Type.INT); - - /** non-null; the list <code>[int, int[], int]</code> */ - public static final StdTypeList INT_INTARR_INT = - StdTypeList.make(Type.INT, Type.INT_ARRAY, Type.INT); - - /** non-null; the list <code>[long, long[], int]</code> */ - public static final StdTypeList LONG_LONGARR_INT = - StdTypeList.make(Type.LONG, Type.LONG_ARRAY, Type.INT); - - /** non-null; the list <code>[float, float[], int]</code> */ - public static final StdTypeList FLOAT_FLOATARR_INT = - StdTypeList.make(Type.FLOAT, Type.FLOAT_ARRAY, Type.INT); - - /** non-null; the list <code>[double, double[], int]</code> */ - public static final StdTypeList DOUBLE_DOUBLEARR_INT = - StdTypeList.make(Type.DOUBLE, Type.DOUBLE_ARRAY, Type.INT); - - /** non-null; the list <code>[Object, Object[], int]</code> */ - public static final StdTypeList OBJECT_OBJECTARR_INT = - StdTypeList.make(Type.OBJECT, Type.OBJECT_ARRAY, Type.INT); - - /** non-null; the list <code>[int, boolean[], int]</code> */ - public static final StdTypeList INT_BOOLEANARR_INT = - StdTypeList.make(Type.INT, Type.BOOLEAN_ARRAY, Type.INT); - - /** non-null; the list <code>[int, byte[], int]</code> */ - public static final StdTypeList INT_BYTEARR_INT = - StdTypeList.make(Type.INT, Type.BYTE_ARRAY, Type.INT); - - /** non-null; the list <code>[int, char[], int]</code> */ - public static final StdTypeList INT_CHARARR_INT = - StdTypeList.make(Type.INT, Type.CHAR_ARRAY, Type.INT); - - /** non-null; the list <code>[int, short[], int]</code> */ - public static final StdTypeList INT_SHORTARR_INT = - StdTypeList.make(Type.INT, Type.SHORT_ARRAY, Type.INT); - - /** - * Makes a single-element instance. - * - * @param type non-null; the element - * @return non-null; an appropriately-constructed instance - */ - public static StdTypeList make(Type type) { - StdTypeList result = new StdTypeList(1); - result.set(0, type); - return result; - } - - /** - * Makes a two-element instance. - * - * @param type0 non-null; the first element - * @param type1 non-null; the second element - * @return non-null; an appropriately-constructed instance - */ - public static StdTypeList make(Type type0, Type type1) { - StdTypeList result = new StdTypeList(2); - result.set(0, type0); - result.set(1, type1); - return result; - } - - /** - * Makes a three-element instance. - * - * @param type0 non-null; the first element - * @param type1 non-null; the second element - * @param type2 non-null; the third element - * @return non-null; an appropriately-constructed instance - */ - public static StdTypeList make(Type type0, Type type1, Type type2) { - StdTypeList result = new StdTypeList(3); - result.set(0, type0); - result.set(1, type1); - result.set(2, type2); - return result; - } - - /** - * Makes a four-element instance. - * - * @param type0 non-null; the first element - * @param type1 non-null; the second element - * @param type2 non-null; the third element - * @param type3 non-null; the fourth element - * @return non-null; an appropriately-constructed instance - */ - public static StdTypeList make(Type type0, Type type1, Type type2, - Type type3) { - StdTypeList result = new StdTypeList(4); - result.set(0, type0); - result.set(1, type1); - result.set(2, type2); - result.set(3, type3); - return result; - } - - /** - * Returns the given list as a comma-separated list of human forms. This - * is a static method so as to work on arbitrary {@link TypeList} - * instances. - * - * @param list non-null; the list to convert - * @return non-null; the human form - */ - public static String toHuman(TypeList list) { - int size = list.size(); - - if (size == 0) { - return "<empty>"; - } - - StringBuffer sb = new StringBuffer(100); - - for (int i = 0; i < size; i++) { - if (i != 0) { - sb.append(", "); - } - sb.append(list.getType(i).toHuman()); - } - - return sb.toString(); - } - - /** - * Returns a hashcode of the contents of the given list. This - * is a static method so as to work on arbitrary {@link TypeList} - * instances. - * - * @param list non-null; the list to inspect - * @return non-null; the hash code - */ - public static int hashContents(TypeList list) { - int size = list.size(); - int hash = 0; - - for (int i = 0; i < size; i++) { - hash = (hash * 31) + list.getType(i).hashCode(); - } - - return hash; - } - - /** - * Compares the contents of the given two instances for equality. This - * is a static method so as to work on arbitrary {@link TypeList} - * instances. - * - * @param list1 non-null; one list to compare - * @param list2 non-null; another list to compare - * @return whether the two lists contain corresponding equal elements - */ - public static boolean equalContents(TypeList list1, TypeList list2) { - int size = list1.size(); - - if (list2.size() != size) { - return false; - } - - for (int i = 0; i < size; i++) { - if (! list1.getType(i).equals(list2.getType(i))) { - return false; - } - } - - return true; - } - - /** - * Compares the contents of the given two instances for ordering. This - * is a static method so as to work on arbitrary {@link TypeList} - * instances. - * - * @param list1 non-null; one list to compare - * @param list2 non-null; another list to compare - * @return the order of the two lists - */ - public static int compareContents(TypeList list1, TypeList list2) { - int size1 = list1.size(); - int size2 = list2.size(); - int size = Math.min(size1, size2); - - for (int i = 0; i < size; i++) { - int comparison = list1.getType(i).compareTo(list2.getType(i)); - if (comparison != 0) { - return comparison; - } - } - - if (size1 == size2) { - return 0; - } else if (size1 < size2) { - return -1; - } else { - return 1; - } - } - - /** - * Constructs an instance. All indices initially contain <code>null</code>. - * - * @param size the size of the list - */ - public StdTypeList(int size) { - super(size); - } - - /** {@inheritDoc} */ - public Type getType(int n) { - return get(n); - } - - /** {@inheritDoc} */ - public int getWordCount() { - int sz = size(); - int result = 0; - - for (int i = 0; i < sz; i++) { - result += get(i).getCategory(); - } - - return result; - } - - /** {@inheritDoc} */ - public TypeList withAddedType(Type type) { - int sz = size(); - StdTypeList result = new StdTypeList(sz + 1); - - for (int i = 0; i < sz; i++) { - result.set0(i, get0(i)); - } - - result.set(sz, type); - result.setImmutable(); - return result; - } - - /** - * 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</code>. - * - * @param n >= 0, < size(); which element - * @return non-null; the indicated element - */ - public Type get(int n) { - return (Type) get0(n); - } - - /** - * Sets the type at the given index. - * - * @param n >= 0, < size(); which element - * @param type non-null; the type to store - */ - public void set(int n, Type type) { - set0(n, type); - } - - /** - * Returns a new instance, which is the same as this instance, - * except that it has an additional type prepended to the - * original. - * - * @param type non-null; the new first element - * @return non-null; an appropriately-constructed instance - */ - public StdTypeList withFirst(Type type) { - int sz = size(); - StdTypeList result = new StdTypeList(sz + 1); - - result.set0(0, type); - for (int i = 0; i < sz; i++) { - result.set0(i + 1, getOrNull0(i)); - } - - return result; - } -} diff --git a/dx/src/com/android/dx/rop/type/Type.java b/dx/src/com/android/dx/rop/type/Type.java deleted file mode 100644 index 09ea2e26d..000000000 --- a/dx/src/com/android/dx/rop/type/Type.java +++ /dev/null @@ -1,855 +0,0 @@ -/* - * 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.type; - -import com.android.dx.util.Hex; - -import java.util.HashMap; - -/** - * Representation of a value type, such as may appear in a field, in a - * local, on a stack, or in a method descriptor. Instances of this - * class are generally interned and may be usefully compared with each - * other using <code>==</code>. - */ -public final class Type implements TypeBearer, Comparable<Type> { - /** non-null; intern table mapping string descriptors to instances */ - private static final HashMap<String, Type> internTable = - new HashMap<String, Type>(500); - - /** basic type constant for <code>void</code> */ - public static final int BT_VOID = 0; - - /** basic type constant for <code>boolean</code> */ - public static final int BT_BOOLEAN = 1; - - /** basic type constant for <code>byte</code> */ - public static final int BT_BYTE = 2; - - /** basic type constant for <code>char</code> */ - public static final int BT_CHAR = 3; - - /** basic type constant for <code>double</code> */ - public static final int BT_DOUBLE = 4; - - /** basic type constant for <code>float</code> */ - public static final int BT_FLOAT = 5; - - /** basic type constant for <code>int</code> */ - public static final int BT_INT = 6; - - /** basic type constant for <code>long</code> */ - public static final int BT_LONG = 7; - - /** basic type constant for <code>short</code> */ - public static final int BT_SHORT = 8; - - /** basic type constant for <code>Object</code> */ - public static final int BT_OBJECT = 9; - - /** basic type constant for a return address */ - public static final int BT_ADDR = 10; - - /** count of basic type constants */ - public static final int BT_COUNT = 11; - - /** non-null; instance representing <code>boolean</code> */ - public static final Type BOOLEAN = new Type("Z", BT_BOOLEAN); - - /** non-null; instance representing <code>byte</code> */ - public static final Type BYTE = new Type("B", BT_BYTE); - - /** non-null; instance representing <code>char</code> */ - public static final Type CHAR = new Type("C", BT_CHAR); - - /** non-null; instance representing <code>double</code> */ - public static final Type DOUBLE = new Type("D", BT_DOUBLE); - - /** non-null; instance representing <code>float</code> */ - public static final Type FLOAT = new Type("F", BT_FLOAT); - - /** non-null; instance representing <code>int</code> */ - public static final Type INT = new Type("I", BT_INT); - - /** non-null; instance representing <code>long</code> */ - public static final Type LONG = new Type("J", BT_LONG); - - /** non-null; instance representing <code>short</code> */ - public static final Type SHORT = new Type("S", BT_SHORT); - - /** non-null; instance representing <code>void</code> */ - public static final Type VOID = new Type("V", BT_VOID); - - /** non-null; instance representing a known-<code>null</code> */ - public static final Type KNOWN_NULL = new Type("<null>", BT_OBJECT); - - /** non-null; instance representing a subroutine return address */ - public static final Type RETURN_ADDRESS = new Type("<addr>", BT_ADDR); - - static { - /* - * Put all the primitive types into the intern table. This needs - * to happen before the array types below get interned. - */ - putIntern(BOOLEAN); - putIntern(BYTE); - putIntern(CHAR); - putIntern(DOUBLE); - putIntern(FLOAT); - putIntern(INT); - putIntern(LONG); - putIntern(SHORT); - /* - * Note: VOID isn't put in the intern table, since it's special and - * shouldn't be found by a normal call to intern(). - */ - } - - /** - * non-null; instance representing - * <code>java.lang.annotation.Annotation</code> - */ - public static final Type ANNOTATION = - intern("Ljava/lang/annotation/Annotation;"); - - /** non-null; instance representing <code>java.lang.Class</code> */ - public static final Type CLASS = intern("Ljava/lang/Class;"); - - /** non-null; instance representing <code>java.lang.Cloneable</code> */ - public static final Type CLONEABLE = intern("Ljava/lang/Cloneable;"); - - /** non-null; instance representing <code>java.lang.Object</code> */ - public static final Type OBJECT = intern("Ljava/lang/Object;"); - - /** non-null; instance representing <code>java.io.Serializable</code> */ - public static final Type SERIALIZABLE = intern("Ljava/io/Serializable;"); - - /** non-null; instance representing <code>java.lang.String</code> */ - public static final Type STRING = intern("Ljava/lang/String;"); - - /** non-null; instance representing <code>java.lang.Throwable</code> */ - public static final Type THROWABLE = intern("Ljava/lang/Throwable;"); - - /** - * non-null; instance representing <code>java.lang.Boolean</code>; the - * suffix on the name helps disambiguate this from the instance - * representing a primitive type - */ - public static final Type BOOLEAN_CLASS = intern("Ljava/lang/Boolean;"); - - /** - * non-null; instance representing <code>java.lang.Byte</code>; the - * suffix on the name helps disambiguate this from the instance - * representing a primitive type - */ - public static final Type BYTE_CLASS = intern("Ljava/lang/Byte;"); - - /** - * non-null; instance representing <code>java.lang.Character</code>; the - * suffix on the name helps disambiguate this from the instance - * representing a primitive type - */ - public static final Type CHARACTER_CLASS = intern("Ljava/lang/Character;"); - - /** - * non-null; instance representing <code>java.lang.Double</code>; the - * suffix on the name helps disambiguate this from the instance - * representing a primitive type - */ - public static final Type DOUBLE_CLASS = intern("Ljava/lang/Double;"); - - /** - * non-null; instance representing <code>java.lang.Float</code>; the - * suffix on the name helps disambiguate this from the instance - * representing a primitive type - */ - public static final Type FLOAT_CLASS = intern("Ljava/lang/Float;"); - - /** - * non-null; instance representing <code>java.lang.Integer</code>; the - * suffix on the name helps disambiguate this from the instance - * representing a primitive type - */ - public static final Type INTEGER_CLASS = intern("Ljava/lang/Integer;"); - - /** - * non-null; instance representing <code>java.lang.Long</code>; the - * suffix on the name helps disambiguate this from the instance - * representing a primitive type - */ - public static final Type LONG_CLASS = intern("Ljava/lang/Long;"); - - /** - * non-null; instance representing <code>java.lang.Short</code>; the - * suffix on the name helps disambiguate this from the instance - * representing a primitive type - */ - public static final Type SHORT_CLASS = intern("Ljava/lang/Short;"); - - /** - * non-null; instance representing <code>java.lang.Void</code>; the - * suffix on the name helps disambiguate this from the instance - * representing a primitive type - */ - public static final Type VOID_CLASS = intern("Ljava/lang/Void;"); - - /** non-null; instance representing <code>boolean[]</code> */ - public static final Type BOOLEAN_ARRAY = BOOLEAN.getArrayType(); - - /** non-null; instance representing <code>byte[]</code> */ - public static final Type BYTE_ARRAY = BYTE.getArrayType(); - - /** non-null; instance representing <code>char[]</code> */ - public static final Type CHAR_ARRAY = CHAR.getArrayType(); - - /** non-null; instance representing <code>double[]</code> */ - public static final Type DOUBLE_ARRAY = DOUBLE.getArrayType(); - - /** non-null; instance representing <code>float[]</code> */ - public static final Type FLOAT_ARRAY = FLOAT.getArrayType(); - - /** non-null; instance representing <code>int[]</code> */ - public static final Type INT_ARRAY = INT.getArrayType(); - - /** non-null; instance representing <code>long[]</code> */ - public static final Type LONG_ARRAY = LONG.getArrayType(); - - /** non-null; instance representing <code>Object[]</code> */ - public static final Type OBJECT_ARRAY = OBJECT.getArrayType(); - - /** non-null; instance representing <code>short[]</code> */ - public static final Type SHORT_ARRAY = SHORT.getArrayType(); - - /** non-null; field descriptor for the type */ - private final String descriptor; - - /** - * basic type corresponding to this type; one of the - * <code>BT_*</code> constants - */ - private final int basicType; - - /** - * >= -1; for an uninitialized type, bytecode index that this - * instance was allocated at; <code>Integer.MAX_VALUE</code> if it - * was an incoming uninitialized instance; <code>-1</code> if this - * is an <i>inititialized</i> instance - */ - private final int newAt; - - /** - * null-ok; the internal-form class name corresponding to this type, if - * calculated; only valid if <code>this</code> is a reference type and - * additionally not a return address - */ - private String className; - - /** - * null-ok; the type corresponding to an array of this type, if - * calculated - */ - private Type arrayType; - - /** - * null-ok; the type corresponding to elements of this type, if - * calculated; only valid if <code>this</code> is an array type - */ - private Type componentType; - - /** - * null-ok; the type corresponding to the initialized version of - * this type, if this instance is in fact an uninitialized type - */ - private Type initializedType; - - /** - * Returns the unique instance corresponding to the type with the - * given descriptor. See vmspec-2 sec4.3.2 for details on the - * field descriptor syntax. This method does <i>not</i> allow - * <code>"V"</code> (that is, type <code>void</code>) as a valid - * descriptor. - * - * @param descriptor non-null; the descriptor - * @return non-null; the corresponding instance - * @throws IllegalArgumentException thrown if the descriptor has - * invalid syntax - */ - public static Type intern(String descriptor) { - Type result = internTable.get(descriptor); - if (result != null) { - return result; - } - - char firstChar; - try { - firstChar = descriptor.charAt(0); - } catch (IndexOutOfBoundsException ex) { - // Translate the exception. - throw new IllegalArgumentException("descriptor is empty"); - } catch (NullPointerException ex) { - // Elucidate the exception. - throw new NullPointerException("descriptor == null"); - } - - if (firstChar == '[') { - /* - * Recursively strip away array markers to get at the underlying - * type, and build back on to form the result. - */ - result = intern(descriptor.substring(1)); - return result.getArrayType(); - } - - /* - * If the first character isn't '[' and it wasn't found in the - * intern cache, then it had better be the descriptor for a class. - */ - - int length = descriptor.length(); - if ((firstChar != 'L') || - (descriptor.charAt(length - 1) != ';')) { - throw new IllegalArgumentException("bad descriptor"); - } - - /* - * Validate the characters of the class name itself. Note that - * vmspec-2 does not have a coherent definition for valid - * internal-form class names, and the definition here is fairly - * liberal: A name is considered valid as long as it doesn't - * contain any of '[' ';' '.' '(' ')', and it has no more than one - * '/' in a row, and no '/' at either end. - */ - - int limit = (length - 1); // Skip the final ';'. - for (int i = 1; i < limit; i++) { - char c = descriptor.charAt(i); - switch (c) { - case '[': - case ';': - case '.': - case '(': - case ')': { - throw new IllegalArgumentException("bad descriptor"); - } - case '/': { - if ((i == 1) || - (i == (length - 1)) || - (descriptor.charAt(i - 1) == '/')) { - throw new IllegalArgumentException("bad descriptor"); - } - break; - } - } - } - - result = new Type(descriptor, BT_OBJECT); - return putIntern(result); - } - - /** - * Returns the unique instance corresponding to the type with the - * given descriptor, allowing <code>"V"</code> to return the type - * for <code>void</code>. Other than that one caveat, this method - * is identical to {@link #intern}. - * - * @param descriptor non-null; the descriptor - * @return non-null; the corresponding instance - * @throws IllegalArgumentException thrown if the descriptor has - * invalid syntax - */ - public static Type internReturnType(String descriptor) { - try { - if (descriptor.equals("V")) { - // This is the one special case where void may be returned. - return VOID; - } - } catch (NullPointerException ex) { - // Elucidate the exception. - throw new NullPointerException("descriptor == null"); - } - - return intern(descriptor); - } - - /** - * Returns the unique instance corresponding to the type of the - * class with the given name. Calling this method is equivalent to - * calling <code>intern(name)</code> if <code>name</code> begins - * with <code>"["</code> and calling <code>intern("L" + name + ";")</code> - * in all other cases. - * - * @param name non-null; the name of the class whose type is desired - * @return non-null; the corresponding type - * @throws IllegalArgumentException thrown if the name has - * invalid syntax - */ - public static Type internClassName(String name) { - if (name == null) { - throw new NullPointerException("name == null"); - } - - if (name.startsWith("[")) { - return intern(name); - } - - return intern('L' + name + ';'); - } - - /** - * Constructs an instance corresponding to an "uninitialized type." - * This is a private constructor; use one of the public static - * methods to get instances. - * - * @param descriptor non-null; the field descriptor for the type - * @param basicType basic type corresponding to this type; one of the - * <code>BT_*</code> constants - * @param newAt >= -1 allocation bytecode index - */ - private Type(String descriptor, int basicType, int newAt) { - if (descriptor == null) { - throw new NullPointerException("descriptor == null"); - } - - if ((basicType < 0) || (basicType >= BT_COUNT)) { - throw new IllegalArgumentException("bad basicType"); - } - - if (newAt < -1) { - throw new IllegalArgumentException("newAt < -1"); - } - - this.descriptor = descriptor; - this.basicType = basicType; - this.newAt = newAt; - this.arrayType = null; - this.componentType = null; - this.initializedType = null; - } - - /** - * Constructs an instance corresponding to an "initialized type." - * This is a private constructor; use one of the public static - * methods to get instances. - * - * @param descriptor non-null; the field descriptor for the type - * @param basicType basic type corresponding to this type; one of the - * <code>BT_*</code> constants - */ - private Type(String descriptor, int basicType) { - this(descriptor, basicType, -1); - } - - /** {@inheritDoc} */ - @Override - public boolean equals(Object other) { - if (this == other) { - /* - * Since externally-visible types are interned, this check - * helps weed out some easy cases. - */ - return true; - } - - if (!(other instanceof Type)) { - return false; - } - - return descriptor.equals(((Type) other).descriptor); - } - - /** {@inheritDoc} */ - @Override - public int hashCode() { - return descriptor.hashCode(); - } - - /** {@inheritDoc} */ - public int compareTo(Type other) { - return descriptor.compareTo(other.descriptor); - } - - /** {@inheritDoc} */ - @Override - public String toString() { - return descriptor; - } - - /** {@inheritDoc} */ - public String toHuman() { - switch (basicType) { - case BT_VOID: return "void"; - case BT_BOOLEAN: return "boolean"; - case BT_BYTE: return "byte"; - case BT_CHAR: return "char"; - case BT_DOUBLE: return "double"; - case BT_FLOAT: return "float"; - case BT_INT: return "int"; - case BT_LONG: return "long"; - case BT_SHORT: return "short"; - case BT_OBJECT: break; - default: return descriptor; - } - - if (isArray()) { - return getComponentType().toHuman() + "[]"; - } - - // Remove the "L...;" around the type and convert "/" to ".". - return getClassName().replace("/", "."); - } - - /** {@inheritDoc} */ - public Type getType() { - return this; - } - - /** {@inheritDoc} */ - public Type getFrameType() { - switch (basicType) { - case BT_BOOLEAN: - case BT_BYTE: - case BT_CHAR: - case BT_INT: - case BT_SHORT: { - return INT; - } - } - - return this; - } - - /** {@inheritDoc} */ - public int getBasicType() { - return basicType; - } - - /** {@inheritDoc} */ - public int getBasicFrameType() { - switch (basicType) { - case BT_BOOLEAN: - case BT_BYTE: - case BT_CHAR: - case BT_INT: - case BT_SHORT: { - return BT_INT; - } - } - - return basicType; - } - - /** {@inheritDoc} */ - public boolean isConstant() { - return false; - } - - /** - * Gets the descriptor. - * - * @return non-null; the descriptor - */ - public String getDescriptor() { - return descriptor; - } - - /** - * Gets the name of the class this type corresponds to, in internal - * form. This method is only valid if this instance is for a - * normal reference type (that is, a reference type and - * additionally not a return address). - * - * @return non-null; the internal-form class name - */ - public String getClassName() { - if (className == null) { - if (!isReference()) { - throw new IllegalArgumentException("not an object type: " + - descriptor); - } - - if (descriptor.charAt(0) == '[') { - className = descriptor; - } else { - className = descriptor.substring(1, descriptor.length() - 1); - } - } - - return className; - } - - /** - * Gets the category. Most instances are category 1. <code>long</code> - * and <code>double</code> are the only category 2 types. - * - * @see #isCategory1 - * @see #isCategory2 - * @return the category - */ - public int getCategory() { - switch (basicType) { - case BT_LONG: - case BT_DOUBLE: { - return 2; - } - } - - return 1; - } - - /** - * Returns whether or not this is a category 1 type. - * - * @see #getCategory - * @see #isCategory2 - * @return whether or not this is a category 1 type - */ - public boolean isCategory1() { - switch (basicType) { - case BT_LONG: - case BT_DOUBLE: { - return false; - } - } - - return true; - } - - /** - * Returns whether or not this is a category 2 type. - * - * @see #getCategory - * @see #isCategory1 - * @return whether or not this is a category 2 type - */ - public boolean isCategory2() { - switch (basicType) { - case BT_LONG: - case BT_DOUBLE: { - return true; - } - } - - return false; - } - - /** - * Gets whether this type is "intlike." An intlike type is one which, when - * placed on a stack or in a local, is automatically converted to an - * <code>int</code>. - * - * @return whether this type is "intlike" - */ - public boolean isIntlike() { - switch (basicType) { - case BT_BOOLEAN: - case BT_BYTE: - case BT_CHAR: - case BT_INT: - case BT_SHORT: { - return true; - } - } - - return false; - } - - /** - * Gets whether this type is a primitive type. All types are either - * primitive or reference types. - * - * @return whether this type is primitive - */ - public boolean isPrimitive() { - switch (basicType) { - case BT_BOOLEAN: - case BT_BYTE: - case BT_CHAR: - case BT_DOUBLE: - case BT_FLOAT: - case BT_INT: - case BT_LONG: - case BT_SHORT: - case BT_VOID: { - return true; - } - } - - return false; - } - - /** - * Gets whether this type is a normal reference type. A normal - * reference type is a reference type that is not a return - * address. This method is just convenient shorthand for - * <code>getBasicType() == Type.BT_OBJECT</code>. - * - * @return whether this type is a normal reference type - */ - public boolean isReference() { - return (basicType == BT_OBJECT); - } - - /** - * Gets whether this type is an array type. If this method returns - * <code>true</code>, then it is safe to use {@link #getComponentType} - * to determine the component type. - * - * @return whether this type is an array type - */ - public boolean isArray() { - return (descriptor.charAt(0) == '['); - } - - /** - * Gets whether this type is an array type or is a known-null, and - * hence is compatible with array types. - * - * @return whether this type is an array type - */ - public boolean isArrayOrKnownNull() { - return isArray() || equals(KNOWN_NULL); - } - - /** - * Gets whether this type represents an uninitialized instance. An - * uninitialized instance is what one gets back from the <code>new</code> - * opcode, and remains uninitialized until a valid constructor is - * invoked on it. - * - * @return whether this type is "uninitialized" - */ - public boolean isUninitialized() { - return (newAt >= 0); - } - - /** - * Gets the bytecode index at which this uninitialized type was - * allocated. This returns <code>Integer.MAX_VALUE</code> if this - * type is an uninitialized incoming parameter (i.e., the - * <code>this</code> of an <code><init></code> method) or - * <code>-1</code> if this type is in fact <i>initialized</i>. - * - * @return >= -1; the allocation bytecode index - */ - public int getNewAt() { - return newAt; - } - - /** - * Gets the initialized type corresponding to this instance, but only - * if this instance is in fact an uninitialized object type. - * - * @return non-null; the initialized type - */ - public Type getInitializedType() { - if (initializedType == null) { - throw new IllegalArgumentException("initialized type: " + - descriptor); - } - - return initializedType; - } - - /** - * Gets the type corresponding to an array of this type. - * - * @return non-null; the array type - */ - public Type getArrayType() { - if (arrayType == null) { - arrayType = putIntern(new Type('[' + descriptor, BT_OBJECT)); - } - - return arrayType; - } - - /** - * Gets the component type of this type. This method is only valid on - * array types. - * - * @return non-null; the component type - */ - public Type getComponentType() { - if (componentType == null) { - if (descriptor.charAt(0) != '[') { - throw new IllegalArgumentException("not an array type: " + - descriptor); - } - componentType = intern(descriptor.substring(1)); - } - - return componentType; - } - - /** - * Returns a new interned instance which is identical to this one, except - * it is indicated as uninitialized and allocated at the given bytecode - * index. This instance must be an initialized object type. - * - * @param newAt >= 0; the allocation bytecode index - * @return non-null; an appropriately-constructed instance - */ - public Type asUninitialized(int newAt) { - if (newAt < 0) { - throw new IllegalArgumentException("newAt < 0"); - } - - if (!isReference()) { - throw new IllegalArgumentException("not a reference type: " + - descriptor); - } - - if (isUninitialized()) { - /* - * Dealing with uninitialized types as a starting point is - * a pain, and it's not clear that it'd ever be used, so - * just disallow it. - */ - throw new IllegalArgumentException("already uninitialized: " + - descriptor); - } - - /* - * Create a new descriptor that is unique and shouldn't conflict - * with "normal" type descriptors - */ - String newDesc = 'N' + Hex.u2(newAt) + descriptor; - Type result = new Type(newDesc, BT_OBJECT, newAt); - result.initializedType = this; - return putIntern(result); - } - - /** - * Puts the given instance in the intern table if it's not already - * there. If a conflicting value is already in the table, then leave it. - * Return the interned value. - * - * @param type non-null; instance to make interned - * @return non-null; the actual interned object - */ - private static Type putIntern(Type type) { - synchronized (internTable) { - String descriptor = type.getDescriptor(); - Type already = internTable.get(descriptor); - if (already != null) { - return already; - } - internTable.put(descriptor, type); - return type; - } - } -} diff --git a/dx/src/com/android/dx/rop/type/TypeBearer.java b/dx/src/com/android/dx/rop/type/TypeBearer.java deleted file mode 100644 index b9e4ea576..000000000 --- a/dx/src/com/android/dx/rop/type/TypeBearer.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.type; - -import com.android.dx.util.ToHuman; - -/** - * Object which has an associated type, possibly itself. - */ -public interface TypeBearer - extends ToHuman { - /** - * Gets the type associated with this instance. - * - * @return non-null; the type - */ - public Type getType(); - - /** - * Gets the frame type corresponding to this type. This method returns - * <code>this</code>, except if {@link Type#isIntlike} on the underlying - * type returns <code>true</code> but the underlying type is not in - * fact {@link Type#INT}, in which case this method returns an instance - * whose underlying type <i>is</i> <code>INT</code>. - * - * @return non-null; the frame type for this instance - */ - public TypeBearer getFrameType(); - - /** - * Gets the basic type corresponding to this instance. - * - * @return the basic type; one of the <code>BT_*</code> constants - * defined by {@link Type} - */ - public int getBasicType(); - - /** - * Gets the basic type corresponding to this instance's frame type. This - * is equivalent to <code>getFrameType().getBasicType()</code>, and - * is the same as calling <code>getFrameType()</code> unless this - * instance is an int-like type, in which case this method returns - * <code>BT_INT</code>. - * - * @see #getBasicType - * @see #getFrameType - * - * @return the basic frame type; one of the <code>BT_*</code> constants - * defined by {@link Type} - */ - public int getBasicFrameType(); - - /** - * Returns whether this instance represents a constant value. - * - * @return <code>true</code> if this instance represents a constant value - * and <code>false</code> if not - */ - public boolean isConstant(); -} diff --git a/dx/src/com/android/dx/rop/type/TypeList.java b/dx/src/com/android/dx/rop/type/TypeList.java deleted file mode 100644 index 0944fe271..000000000 --- a/dx/src/com/android/dx/rop/type/TypeList.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.type; - -/** - * List of {@link Type} instances (or of things that contain types). - */ -public interface TypeList { - /** - * Returns whether this instance is mutable. Note that the - * <code>TypeList</code> interface itself doesn't provide any - * means of mutation, but that doesn't mean that there isn't an - * extra-interface way of mutating an instance. - * - * @return <code>true</code> if this instance is mutable or - * <code>false</code> if it is immutable - */ - public boolean isMutable(); - - /** - * Gets the size of this list. - * - * @return >= 0; the size - */ - public int size(); - - /** - * 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</code>. - * - * @param n >= 0, < size(); which element - * @return non-null; the indicated element - */ - public Type getType(int n); - - /** - * Gets the number of 32-bit words required to hold instances of - * all the elements of this list. This is a sum of the widths (categories) - * of all the elements. - * - * @return >= 0; the required number of words - */ - public int getWordCount(); - - /** - * Returns a new instance which is identical to this one, except that - * the given item is appended to the end and it is guaranteed to be - * immutable. - * - * @param type non-null; item to append - * @return non-null; an appropriately-constructed instance - */ - public TypeList withAddedType(Type type); -} diff --git a/dx/src/com/android/dx/rop/type/package.html b/dx/src/com/android/dx/rop/type/package.html deleted file mode 100644 index 93d9d5f0b..000000000 --- a/dx/src/com/android/dx/rop/type/package.html +++ /dev/null @@ -1,8 +0,0 @@ -<body> -<p>Implementation of classes that represent types (classes or primitives).</p> - -<p><b>PACKAGES USED:</b> -<ul> -<li><code>com.android.dx.util</code></li> -</ul> -</body> |