1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/*
2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project
3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License");
5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License.
6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at
7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *      http://www.apache.org/licenses/LICENSE-2.0
9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul *
10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software
11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS,
12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and
14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License.
15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.rop.code;
18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.Constant;
20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.cst.CstUtf8;
21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.Type;
22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.rop.type.TypeBearer;
23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.ToHuman;
24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.HashMap;
26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/**
28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Combination of a register number and a type, used as the sources and
29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * destinations of register-based operations.
30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class RegisterSpec
32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        implements TypeBearer, ToHuman, Comparable<RegisterSpec> {
33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} string to prefix register numbers with */
34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static final String PREFIX = "v";
35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} intern table for instances */
37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final HashMap<Object, RegisterSpec> theInterns =
38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        new HashMap<Object, RegisterSpec>(1000);
39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} common comparison instance used while interning */
41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static final ForComparison theInterningItem = new ForComparison();
42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code >= 0;} register number */
44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final int reg;
45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} type loaded or stored */
47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final TypeBearer type;
48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code null-ok;} local variable info associated with this register, if any */
50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final LocalItem local;
51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Intern the given triple as an instance of this class.
54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param reg {@code >= 0;} the register number
56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param type {@code non-null;} the type (or possibly actual value) which
57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * is loaded from or stored to the indicated register
58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param local {@code null-ok;} the associated local variable, if any
59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} an appropriately-constructed instance
60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static RegisterSpec intern(int reg, TypeBearer type,
62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            LocalItem local) {
63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        theInterningItem.set(reg, type, local);
64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        RegisterSpec found = theInterns.get(theInterningItem);
65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (found != null) {
67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return found;
68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        found = theInterningItem.toRegisterSpec();
71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        theInterns.put(found, found);
72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return found;
73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an instance for the given register number and type, with
77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * no variable info. This method is allowed to return shared
78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * instances (but doesn't necessarily do so).
79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param reg {@code >= 0;} the register number
81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param type {@code non-null;} the type (or possibly actual value) which
82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * is loaded from or stored to the indicated register
83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} an appropriately-constructed instance
84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static RegisterSpec make(int reg, TypeBearer type) {
86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return intern(reg, type, null);
87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an instance for the given register number, type, and
91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * variable info. This method is allowed to return shared
92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * instances (but doesn't necessarily do so).
93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param reg {@code >= 0;} the register number
95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param type {@code non-null;} the type (or possibly actual value) which
96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * is loaded from or stored to the indicated register
97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param local {@code non-null;} the associated local variable
98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} an appropriately-constructed instance
99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static RegisterSpec make(int reg, TypeBearer type,
101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            LocalItem local) {
102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (local == null) {
103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("local  == null");
104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return intern(reg, type, local);
107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an instance for the given register number, type, and
111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * variable info. This method is allowed to return shared
112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * instances (but doesn't necessarily do so).
113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param reg {@code >= 0;} the register number
115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param type {@code non-null;} the type (or possibly actual value) which
116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * is loaded from or stored to the indicated register
117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param local {@code null-ok;} the associated variable info or null for
118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * none
119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} an appropriately-constructed instance
120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static RegisterSpec makeLocalOptional(
122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            int reg, TypeBearer type, LocalItem local) {
123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return intern(reg, type, local);
125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the string form for the given register number.
129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param reg {@code >= 0;} the register number
131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the string form
132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static String regString(int reg) {
134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return PREFIX + reg;
135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs an instance. This constructor is private. Use
139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@link #make}.
140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param reg {@code >= 0;} the register number
142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param type {@code non-null;} the type (or possibly actual value) which
143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * is loaded from or stored to the indicated register
144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param local {@code null-ok;} the associated local variable, if any
145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private RegisterSpec(int reg, TypeBearer type, LocalItem local) {
147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (reg < 0) {
148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new IllegalArgumentException("reg < 0");
149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (type == null) {
152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("type == null");
153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.reg = reg;
156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.type = type;
157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.local = local;
158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public boolean equals(Object other) {
163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (!(other instanceof RegisterSpec)) {
164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (other instanceof ForComparison) {
165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                ForComparison fc = (ForComparison) other;
166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                return equals(fc.reg, fc.type, fc.local);
167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return false;
169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        RegisterSpec spec = (RegisterSpec) other;
172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return equals(spec.reg, spec.type, spec.local);
173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Like {@code equals}, but only consider the simple types of the
177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * registers. That is, this compares {@code getType()} on the types
178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * to ignore whatever arbitrary extra stuff might be carried around
179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * by an outer {@link TypeBearer}.
180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param other {@code null-ok;} spec to compare to
182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code true} iff {@code this} and {@code other} are equal
183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * in the stated way
184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public boolean equalsUsingSimpleType(RegisterSpec other) {
186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (!matchesVariable(other)) {
187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return false;
188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return (reg == other.reg);
191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Like {@link #equalsUsingSimpleType} but ignoring the register number.
195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * This is useful to determine if two instances refer to the "same"
196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * local variable.
197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param other {@code null-ok;} spec to compare to
199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code true} iff {@code this} and {@code other} are equal
200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * in the stated way
201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public boolean matchesVariable(RegisterSpec other) {
203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (other == null) {
204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return false;
205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return type.getType().equals(other.type.getType())
208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            && ((local == other.local)
209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    || ((local != null) && local.equals(other.local)));
210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Helper for {@link #equals} and {@link #ForComparison.equals},
214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * which actually does the test.
215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param reg value of the instance variable, for another instance
217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param type value of the instance variable, for another instance
218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param local value of the instance variable, for another instance
219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return whether this instance is equal to one with the given
220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * values
221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private boolean equals(int reg, TypeBearer type, LocalItem local) {
223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return (this.reg == reg)
224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            && this.type.equals(type)
225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            && ((this.local == local)
226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    || ((this.local != null) && this.local.equals(local)));
227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Compares by (in priority order) register number, unwrapped type
231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * (that is types not {@link TypeBearer}s, and local info.
232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param other {@code non-null;} spec to compare to
234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code -1..1;} standard result of comparison
235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public int compareTo(RegisterSpec other) {
237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (this.reg < other.reg) {
238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return -1;
239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (this.reg > other.reg) {
240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return 1;
241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int compare = type.getType().compareTo(other.type.getType());
244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (compare != 0) {
246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return compare;
247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (this.local == null) {
250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return (other.local == null) ? 0 : -1;
251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else if (other.local == null) {
252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return 1;
253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return this.local.compareTo(other.local);
256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public int hashCode() {
261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return hashCodeOf(reg, type, local);
262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Helper for {@link #hashCode} and {@link #ForComparison.hashCode},
266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * which actually does the calculation.
267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param reg value of the instance variable
269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param type value of the instance variable
270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param local value of the instance variable
271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return the hash code
272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static int hashCodeOf(int reg, TypeBearer type, LocalItem local) {
274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int hash = (local != null) ? local.hashCode() : 0;
275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        hash = (hash * 31 + type.hashCode()) * 31 + reg;
277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return hash;
278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public String toString() {
283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return toString0(false);
284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public String toHuman() {
288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return toString0(true);
289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public Type getType() {
293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return type.getType();
294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public TypeBearer getFrameType() {
298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return type.getFrameType();
299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final int getBasicType() {
303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return type.getBasicType();
304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final int getBasicFrameType() {
308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return type.getBasicFrameType();
309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public final boolean isConstant() {
313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return false;
314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the register number.
318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code >= 0;} the register number
320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public int getReg() {
322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return reg;
323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the type (or actual value) which is loaded from or stored
327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * to the register associated with this instance.
328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the type
330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public TypeBearer getTypeBearer() {
332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return type;
333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the variable info associated with this instance, if any.
337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code null-ok;} the variable info, or {@code null} if this
339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * instance has none
340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public LocalItem getLocalItem() {
342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return local;
343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the next available register number after the one in this
347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * instance. This is equal to the register number plus the width
348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * (category) of the type used. Among other things, this may also
349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * be used to determine the minimum required register count
350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * implied by this instance.
351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code >= 0;} the required registers size
353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public int getNextReg() {
355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return reg + getCategory();
356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the category of this instance's type. This is just a convenient
360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * shorthand for {@code getType().getCategory()}.
361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
362917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @see #isCategory1
363917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @see #isCategory2
364917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code 1..2;} the category of this instance's type
365917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
366917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public int getCategory() {
367917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return type.getType().getCategory();
368917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
369917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
370917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
371917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets whether this instance's type is category 1. This is just a
372917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * convenient shorthand for {@code getType().isCategory1()}.
373917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
374917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @see #getCategory
375917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @see #isCategory2
376917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return whether or not this instance's type is of category 1
377917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
378917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public boolean isCategory1() {
379917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return type.getType().isCategory1();
380917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
381917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
382917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
383917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets whether this instance's type is category 2. This is just a
384917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * convenient shorthand for {@code getType().isCategory2()}.
385917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
386917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @see #getCategory
387917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @see #isCategory1
388917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return whether or not this instance's type is of category 2
389917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
390917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public boolean isCategory2() {
391917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return type.getType().isCategory2();
392917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
393917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
394917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
395917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the string form for just the register number of this instance.
396917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
397917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the register string form
398917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
399917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public String regString() {
400917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return regString(reg);
401917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
402917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
403917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
404917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an instance that is the intersection between this instance
405917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * and the given one, if any. The intersection is defined as follows:
406917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
407917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * <ul>
408917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *   <li>If {@code other} is {@code null}, then the result
409917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *     is {@code null}.
410917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *   <li>If the register numbers don't match, then the intersection
411917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *     is {@code null}. Otherwise, the register number of the
412917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *     intersection is the same as the one in the two instances.</li>
413917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *   <li>If the types returned by {@code getType()} are not
414917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *     {@code equals()}, then the intersection is null.</li>
415917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *   <li>If the type bearers returned by {@code getTypeBearer()}
416917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *     are {@code equals()}, then the intersection's type bearer
417917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *     is the one from this instance. Otherwise, the intersection's
418917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *     type bearer is the {@code getType()} of this instance.</li>
419917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *   <li>If the locals are {@code equals()}, then the local info
420917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *     of the intersection is the local info of this instance. Otherwise,
421917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *     the local info of the intersection is {@code null}.</li>
422917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * </ul>
423917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
424917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param other {@code null-ok;} instance to intersect with (or {@code null})
425917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param localPrimary whether local variables are primary to the
426917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * intersection; if {@code true}, then the only non-null
427917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * results occur when registers being intersected have equal local
428917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * infos (or both have {@code null} local infos)
429917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code null-ok;} the intersection
430917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
431917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public RegisterSpec intersect(RegisterSpec other, boolean localPrimary) {
432917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (this == other) {
433917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            // Easy out.
434917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return this;
435917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
436917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
437917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if ((other == null) || (reg != other.getReg())) {
438917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return null;
439917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
440917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
441917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        LocalItem resultLocal =
442917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            ((local == null) || !local.equals(other.getLocalItem()))
443917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            ? null : local;
444917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        boolean sameName = (resultLocal == local);
445917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
446917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (localPrimary && !sameName) {
447917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return null;
448917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
449917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
450917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        Type thisType = getType();
451917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        Type otherType = other.getType();
452917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
453917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        // Note: Types are always interned.
454917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (thisType != otherType) {
455917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return null;
456917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
457917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
458917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        TypeBearer resultTypeBearer =
459917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            type.equals(other.getTypeBearer()) ? type : thisType;
460917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
461917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if ((resultTypeBearer == type) && sameName) {
462917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            // It turns out that the intersection is "this" after all.
463917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return this;
464917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
465917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
466917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return (resultLocal == null) ? make(reg, resultTypeBearer) :
467917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            make(reg, resultTypeBearer, resultLocal);
468917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
469917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
470917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
471917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an instance that is identical to this one, except that the
472917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * register number is replaced by the given one.
473917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
474917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param newReg {@code >= 0;} the new register number
475917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} an appropriately-constructed instance
476917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
477917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public RegisterSpec withReg(int newReg) {
478917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (reg == newReg) {
479917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return this;
480917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
481917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
482917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return makeLocalOptional(newReg, type, local);
483917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
484917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
485917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
486917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an instance that is identical to this one, except that
487917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * the type is replaced by the given one.
488917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
489917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param newType {@code non-null;} the new type
490917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} an appropriately-constructed instance
491917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
492917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public RegisterSpec withType(TypeBearer newType) {
493917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return makeLocalOptional(reg, newType, local);
494917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
495917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
496917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
497917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an instance that is identical to this one, except that the
498917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * register number is offset by the given amount.
499917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
500917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param delta the amount to offset the register number by
501917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} an appropriately-constructed instance
502917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
503917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public RegisterSpec withOffset(int delta) {
504917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (delta == 0) {
505917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return this;
506917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
507917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
508917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return withReg(reg + delta);
509917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
510917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
511917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
512917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an instance that is identical to this one, except that
513917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * the type bearer is replaced by the actual underlying type
514917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * (thereby stripping off non-type information) with any
515917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * initialization information stripped away as well.
516917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
517917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} an appropriately-constructed instance
518917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
519917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public RegisterSpec withSimpleType() {
520917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        TypeBearer orig = type;
521917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        Type newType;
522917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
523917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (orig instanceof Type) {
524917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            newType = (Type) orig;
525917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } else {
526917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            newType = orig.getType();
527917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
528917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
529917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (newType.isUninitialized()) {
530917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            newType = newType.getInitializedType();
531917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
532917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
533917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (newType == orig) {
534917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return this;
535917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
536917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
537917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return makeLocalOptional(reg, newType, local);
538917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
539917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
540917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
541917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an instance that is identical to this one except that the
542917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * local variable is as specified in the parameter.
543917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
544917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param local {@code null-ok;} the local item or null for none
545917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return an appropriate instance
546917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
547917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public RegisterSpec withLocalItem(LocalItem local) {
548917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if ((this.local== local)
549917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    || ((this.local != null) && this.local.equals(local))) {
550917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
551917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return this;
552917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
553917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
554917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return makeLocalOptional(reg, type, local);
555917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
556917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
557917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
558917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
559917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Helper for {@link #toString} and {@link #toHuman}.
560917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
561917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param human whether to be human-oriented
562917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the string form
563917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
564917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private String toString0(boolean human) {
565917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        StringBuffer sb = new StringBuffer(40);
566917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
567917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(regString());
568917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(":");
569917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
570917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (local != null) {
571917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append(local.toString());
572917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
573917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
574917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        Type justType = type.getType();
575917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append(justType);
576917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
577917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (justType != type) {
578917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            sb.append("=");
579917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (human && (type instanceof Constant)) {
580917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                sb.append(((Constant) type).toHuman());
581917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            } else {
582917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                sb.append(type);
583917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
584917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
585917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
586917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return sb.toString();
587917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
588917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
589917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
590917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Holder of register spec data for the purposes of comparison (so that
591917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code RegisterSpec} itself can still keep {@code final}
592917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * instance variables.
593917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
594917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private static class ForComparison {
595917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@code >= 0;} register number */
596917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private int reg;
597917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
598917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@code non-null;} type loaded or stored */
599917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private TypeBearer type;
600917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
601917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
602917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * {@code null-ok;} local variable associated with this
603917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * register, if any
604917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
605917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        private LocalItem local;
606917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
607917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
608917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Set all the instance variables.
609917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
610917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param reg {@code >= 0;} the register number
611917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param type {@code non-null;} the type (or possibly actual
612917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * value) which is loaded from or stored to the indicated
613917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * register
614917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @param local {@code null-ok;} the associated local variable, if any
615917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @return {@code non-null;} an appropriately-constructed instance
616917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
617917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public void set(int reg, TypeBearer type, LocalItem local) {
618917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.reg = reg;
619917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.type = type;
620917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            this.local = local;
621917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
622917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
623917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /**
624917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * Construct a {@code RegisterSpec} of this instance's
625917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * contents.
626917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         *
627917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         * @return {@code non-null;} an appropriately-constructed instance
628917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul         */
629917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public RegisterSpec toRegisterSpec() {
630917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return new RegisterSpec(reg, type, local);
631917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
632917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
633917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@inheritDoc} */
634917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        @Override
635917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public boolean equals(Object other) {
636917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (!(other instanceof RegisterSpec)) {
637917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                return false;
638917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
639917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
640917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            RegisterSpec spec = (RegisterSpec) other;
641917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return spec.equals(reg, type, local);
642917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
643917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
644917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        /** {@inheritDoc} */
645917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        @Override
646917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        public int hashCode() {
647917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return hashCodeOf(reg, type, local);
648917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
649917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
650917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul}
651