1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.rop.code;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.Constant;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstUtf8;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.TypeBearer;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.ToHuman;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.HashMap;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Combination of a register number and a type, used as the sources and
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * destinations of register-based operations.
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class RegisterSpec
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        implements TypeBearer, ToHuman, Comparable<RegisterSpec> {
3399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} string to prefix register numbers with */
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final String PREFIX = "v";
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} intern table for instances */
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final HashMap<Object, RegisterSpec> theInterns =
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        new HashMap<Object, RegisterSpec>(1000);
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} common comparison instance used while interning */
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final ForComparison theInterningItem = new ForComparison();
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code >= 0;} register number */
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int reg;
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} type loaded or stored */
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final TypeBearer type;
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code null-ok;} local variable info associated with this register, if any */
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final LocalItem local;
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Intern the given triple as an instance of this class.
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
5599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param reg {@code >= 0;} the register number
5699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param type {@code non-null;} the type (or possibly actual value) which
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is loaded from or stored to the indicated register
5899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param local {@code null-ok;} the associated local variable, if any
5999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} an appropriately-constructed instance
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static RegisterSpec intern(int reg, TypeBearer type,
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LocalItem local) {
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        theInterningItem.set(reg, type, local);
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RegisterSpec found = theInterns.get(theInterningItem);
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (found != null) {
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return found;
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        found = theInterningItem.toRegisterSpec();
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        theInterns.put(found, found);
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return found;
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns an instance for the given register number and type, with
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * no variable info. This method is allowed to return shared
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instances (but doesn't necessarily do so).
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
8099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param reg {@code >= 0;} the register number
8199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param type {@code non-null;} the type (or possibly actual value) which
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is loaded from or stored to the indicated register
8399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} an appropriately-constructed instance
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static RegisterSpec make(int reg, TypeBearer type) {
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return intern(reg, type, null);
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns an instance for the given register number, type, and
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * variable info. This method is allowed to return shared
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instances (but doesn't necessarily do so).
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
9499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param reg {@code >= 0;} the register number
9599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param type {@code non-null;} the type (or possibly actual value) which
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is loaded from or stored to the indicated register
9799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param local {@code non-null;} the associated local variable
9899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} an appropriately-constructed instance
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static RegisterSpec make(int reg, TypeBearer type,
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LocalItem local) {
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (local == null) {
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("local  == null");
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return intern(reg, type, local);
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns an instance for the given register number, type, and
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * variable info. This method is allowed to return shared
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instances (but doesn't necessarily do so).
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
11499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param reg {@code >= 0;} the register number
11599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param type {@code non-null;} the type (or possibly actual value) which
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is loaded from or stored to the indicated register
11799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param local {@code null-ok;} the associated variable info or null for
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * none
11999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} an appropriately-constructed instance
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static RegisterSpec makeLocalOptional(
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int reg, TypeBearer type, LocalItem local) {
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return intern(reg, type, local);
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the string form for the given register number.
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
13099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param reg {@code >= 0;} the register number
13199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the string form
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static String regString(int reg) {
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return PREFIX + reg;
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance. This constructor is private. Use
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@link #make}.
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
14199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param reg {@code >= 0;} the register number
14299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param type {@code non-null;} the type (or possibly actual value) which
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * is loaded from or stored to the indicated register
14499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param local {@code null-ok;} the associated local variable, if any
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private RegisterSpec(int reg, TypeBearer type, LocalItem local) {
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (reg < 0) {
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("reg < 0");
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (type == null) {
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("type == null");
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.reg = reg;
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.type = type;
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.local = local;
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean equals(Object other) {
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!(other instanceof RegisterSpec)) {
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (other instanceof ForComparison) {
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ForComparison fc = (ForComparison) other;
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return equals(fc.reg, fc.type, fc.local);
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RegisterSpec spec = (RegisterSpec) other;
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return equals(spec.reg, spec.type, spec.local);
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Like {@code equals}, but only consider the simple types of the
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * registers. That is, this compares {@code getType()} on the types
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to ignore whatever arbitrary extra stuff might be carried around
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * by an outer {@link TypeBearer}.
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
18199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param other {@code null-ok;} spec to compare to
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return {@code true} iff {@code this} and {@code other} are equal
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in the stated way
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean equalsUsingSimpleType(RegisterSpec other) {
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!matchesVariable(other)) {
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (reg == other.reg);
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Like {@link #equalsUsingSimpleType} but ignoring the register number.
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This is useful to determine if two instances refer to the "same"
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * local variable.
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
19899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param other {@code null-ok;} spec to compare to
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return {@code true} iff {@code this} and {@code other} are equal
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in the stated way
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean matchesVariable(RegisterSpec other) {
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (other == null) {
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return false;
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return type.getType().equals(other.type.getType())
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            && ((local == other.local)
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    || ((local != null) && local.equals(other.local)));
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper for {@link #equals} and {@link #ForComparison.equals},
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * which actually does the test.
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param reg value of the instance variable, for another instance
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param type value of the instance variable, for another instance
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param local value of the instance variable, for another instance
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return whether this instance is equal to one with the given
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * values
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private boolean equals(int reg, TypeBearer type, LocalItem local) {
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (this.reg == reg)
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            && this.type.equals(type)
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            && ((this.local == local)
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    || ((this.local != null) && this.local.equals(local)));
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Compares by (in priority order) register number, unwrapped type
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (that is types not {@link TypeBearer}s, and local info.
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
23399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param other {@code non-null;} spec to compare to
23499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code -1..1;} standard result of comparison
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int compareTo(RegisterSpec other) {
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (this.reg < other.reg) {
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return -1;
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (this.reg > other.reg) {
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 1;
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int compare = type.getType().compareTo(other.type.getType());
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (compare != 0) {
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return compare;
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (this.local == null) {
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return (other.local == null) ? 0 : -1;
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (other.local == null) {
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return 1;
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return this.local.compareTo(other.local);
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int hashCode() {
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return hashCodeOf(reg, type, local);
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper for {@link #hashCode} and {@link #ForComparison.hashCode},
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * which actually does the calculation.
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param reg value of the instance variable
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param type value of the instance variable
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param local value of the instance variable
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the hash code
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static int hashCodeOf(int reg, TypeBearer type, LocalItem local) {
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int hash = (local != null) ? local.hashCode() : 0;
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hash = (hash * 31 + type.hashCode()) * 31 + reg;
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return hash;
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String toString() {
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return toString0(false);
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String toHuman() {
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return toString0(true);
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Type getType() {
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return type.getType();
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public TypeBearer getFrameType() {
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return type.getFrameType();
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final int getBasicType() {
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return type.getBasicType();
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final int getBasicFrameType() {
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return type.getBasicFrameType();
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final boolean isConstant() {
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the register number.
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
31999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= 0;} the register number
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getReg() {
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return reg;
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the type (or actual value) which is loaded from or stored
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to the register associated with this instance.
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
32999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the type
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public TypeBearer getTypeBearer() {
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return type;
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the variable info associated with this instance, if any.
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
33899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code null-ok;} the variable info, or {@code null} if this
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instance has none
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public LocalItem getLocalItem() {
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return local;
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the next available register number after the one in this
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instance. This is equal to the register number plus the width
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (category) of the type used. Among other things, this may also
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * be used to determine the minimum required register count
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * implied by this instance.
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
35299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= 0;} the required registers size
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getNextReg() {
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return reg + getCategory();
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the category of this instance's type. This is just a convenient
36099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * shorthand for {@code getType().getCategory()}.
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see #isCategory1
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see #isCategory2
36499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code 1..2;} the category of this instance's type
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getCategory() {
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return type.getType().getCategory();
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets whether this instance's type is category 1. This is just a
37299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * convenient shorthand for {@code getType().isCategory1()}.
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see #getCategory
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see #isCategory2
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return whether or not this instance's type is of category 1
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean isCategory1() {
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return type.getType().isCategory1();
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets whether this instance's type is category 2. This is just a
38499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * convenient shorthand for {@code getType().isCategory2()}.
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see #getCategory
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see #isCategory1
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return whether or not this instance's type is of category 2
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean isCategory2() {
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return type.getType().isCategory2();
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the string form for just the register number of this instance.
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
39799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the register string form
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String regString() {
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return regString(reg);
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns an instance that is the intersection between this instance
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and the given one, if any. The intersection is defined as follows:
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <ul>
40899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *   <li>If {@code other} is {@code null}, then the result
40999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *     is {@code null}.
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *   <li>If the register numbers don't match, then the intersection
41199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *     is {@code null}. Otherwise, the register number of the
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *     intersection is the same as the one in the two instances.</li>
41399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *   <li>If the types returned by {@code getType()} are not
41499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *     {@code equals()}, then the intersection is null.</li>
41599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *   <li>If the type bearers returned by {@code getTypeBearer()}
41699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *     are {@code equals()}, then the intersection's type bearer
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *     is the one from this instance. Otherwise, the intersection's
41899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *     type bearer is the {@code getType()} of this instance.</li>
41999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *   <li>If the locals are {@code equals()}, then the local info
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *     of the intersection is the local info of this instance. Otherwise,
42199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     *     the local info of the intersection is {@code null}.</li>
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * </ul>
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
42499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param other {@code null-ok;} instance to intersect with (or {@code null})
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param localPrimary whether local variables are primary to the
42699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * intersection; if {@code true}, then the only non-null
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * results occur when registers being intersected have equal local
42899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * infos (or both have {@code null} local infos)
42999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code null-ok;} the intersection
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public RegisterSpec intersect(RegisterSpec other, boolean localPrimary) {
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (this == other) {
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Easy out.
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return this;
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((other == null) || (reg != other.getReg())) {
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LocalItem resultLocal =
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ((local == null) || !local.equals(other.getLocalItem()))
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ? null : local;
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean sameName = (resultLocal == local);
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (localPrimary && !sameName) {
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Type thisType = getType();
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Type otherType = other.getType();
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Note: Types are always interned.
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (thisType != otherType) {
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TypeBearer resultTypeBearer =
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            type.equals(other.getTypeBearer()) ? type : thisType;
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((resultTypeBearer == type) && sameName) {
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // It turns out that the intersection is "this" after all.
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return this;
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (resultLocal == null) ? make(reg, resultTypeBearer) :
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            make(reg, resultTypeBearer, resultLocal);
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns an instance that is identical to this one, except that the
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * register number is replaced by the given one.
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
47499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param newReg {@code >= 0;} the new register number
47599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} an appropriately-constructed instance
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public RegisterSpec withReg(int newReg) {
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (reg == newReg) {
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return this;
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return makeLocalOptional(newReg, type, local);
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns an instance that is identical to this one, except that
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the type is replaced by the given one.
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
48999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param newType {@code non-null;} the new type
49099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} an appropriately-constructed instance
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public RegisterSpec withType(TypeBearer newType) {
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return makeLocalOptional(reg, newType, local);
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns an instance that is identical to this one, except that the
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * register number is offset by the given amount.
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param delta the amount to offset the register number by
50199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} an appropriately-constructed instance
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public RegisterSpec withOffset(int delta) {
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (delta == 0) {
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return this;
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return withReg(reg + delta);
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns an instance that is identical to this one, except that
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the type bearer is replaced by the actual underlying type
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (thereby stripping off non-type information) with any
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * initialization information stripped away as well.
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
51799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} an appropriately-constructed instance
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public RegisterSpec withSimpleType() {
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TypeBearer orig = type;
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Type newType;
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (orig instanceof Type) {
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            newType = (Type) orig;
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            newType = orig.getType();
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (newType.isUninitialized()) {
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            newType = newType.getInitializedType();
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (newType == orig) {
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return this;
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return makeLocalOptional(reg, newType, local);
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns an instance that is identical to this one except that the
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * local variable is as specified in the parameter.
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
54499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param local {@code null-ok;} the local item or null for none
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return an appropriate instance
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public RegisterSpec withLocalItem(LocalItem local) {
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((this.local== local)
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    || ((this.local != null) && this.local.equals(local))) {
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return this;
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return makeLocalOptional(reg, type, local);
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper for {@link #toString} and {@link #toHuman}.
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param human whether to be human-oriented
56299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the string form
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private String toString0(boolean human) {
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringBuffer sb = new StringBuffer(40);
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(regString());
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(":");
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (local != null) {
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(local.toString());
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Type justType = type.getType();
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(justType);
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (justType != type) {
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append("=");
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (human && (type instanceof Constant)) {
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sb.append(((Constant) type).toHuman());
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sb.append(type);
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sb.toString();
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Holder of register spec data for the purposes of comparison (so that
59199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code RegisterSpec} itself can still keep {@code final}
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instance variables.
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static class ForComparison {
59599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /** {@code >= 0;} register number */
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private int reg;
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
59899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /** {@code non-null;} type loaded or stored */
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private TypeBearer type;
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
60155423dcd081e30c4fc27b997f127db7b00f1b981Dan Bornstein        /**
60255423dcd081e30c4fc27b997f127db7b00f1b981Dan Bornstein         * {@code null-ok;} local variable associated with this
60355423dcd081e30c4fc27b997f127db7b00f1b981Dan Bornstein         * register, if any
60455423dcd081e30c4fc27b997f127db7b00f1b981Dan Bornstein         */
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private LocalItem local;
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Set all the instance variables.
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
61099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param reg {@code >= 0;} the register number
61155423dcd081e30c4fc27b997f127db7b00f1b981Dan Bornstein         * @param type {@code non-null;} the type (or possibly actual
61255423dcd081e30c4fc27b997f127db7b00f1b981Dan Bornstein         * value) which is loaded from or stored to the indicated
61355423dcd081e30c4fc27b997f127db7b00f1b981Dan Bornstein         * register
61499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param local {@code null-ok;} the associated local variable, if any
61599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code non-null;} an appropriately-constructed instance
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public void set(int reg, TypeBearer type, LocalItem local) {
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.reg = reg;
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.type = type;
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.local = local;
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
62499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * Construct a {@code RegisterSpec} of this instance's
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * contents.
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
62799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code non-null;} an appropriately-constructed instance
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public RegisterSpec toRegisterSpec() {
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return new RegisterSpec(reg, type, local);
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** {@inheritDoc} */
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        @Override
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public boolean equals(Object other) {
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!(other instanceof RegisterSpec)) {
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegisterSpec spec = (RegisterSpec) other;
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return spec.equals(reg, type, local);
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** {@inheritDoc} */
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        @Override
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int hashCode() {
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return hashCodeOf(reg, type, local);
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
651