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.CstUtf8;
20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.MutabilityControl;
21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/**
23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Set of {@link RegisterSpec} instances, where a given register number
24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * may appear only once in the set.
25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */
26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class RegisterSpecSet
27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        extends MutabilityControl {
28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code non-null;} no-element instance */
29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public static final RegisterSpecSet EMPTY = new RegisterSpecSet(0);
30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code non-null;} array of register specs, where each element is
33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code null} or is an instance whose {@code reg}
34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * matches the array index
35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private final RegisterSpec[] specs;
37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@code >= -1;} size of the set or {@code -1} if not yet calculated */
39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    private int size;
40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Constructs an instance. The instance is initially empty.
43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param maxSize {@code >= 0;} the maximum register number (exclusive) that
45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * may be represented in this instance
46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public RegisterSpecSet(int maxSize) {
48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        super(maxSize != 0);
49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.specs = new RegisterSpec[maxSize];
51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        this.size = 0;
52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public boolean equals(Object other) {
57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (!(other instanceof RegisterSpecSet)) {
58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return false;
59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        RegisterSpecSet otherSet = (RegisterSpecSet) other;
62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        RegisterSpec[] otherSpecs = otherSet.specs;
63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int len = specs.length;
64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if ((len != otherSpecs.length) || (size() != otherSet.size())) {
66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return false;
67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < len; i++) {
70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            RegisterSpec s1 = specs[i];
71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            RegisterSpec s2 = otherSpecs[i];
72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (s1 == s2) {
74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                continue;
75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if ((s1 == null) || !s1.equals(s2)) {
78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                return false;
79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return true;
83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public int hashCode() {
88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int len = specs.length;
89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int hash = 0;
90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < len; i++) {
92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            RegisterSpec spec = specs[i];
93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            int oneHash = (spec == null) ? 0 : spec.hashCode();
94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            hash = (hash * 31) + oneHash;
95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return hash;
98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /** {@inheritDoc} */
101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    @Override
102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public String toString() {
103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int len = specs.length;
104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        StringBuffer sb = new StringBuffer(len * 25);
105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append('{');
107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        boolean any = false;
109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < len; i++) {
110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            RegisterSpec spec = specs[i];
111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (spec != null) {
112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                if (any) {
113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    sb.append(", ");
114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                } else {
115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    any = true;
116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                }
117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                sb.append(spec);
118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        sb.append('}');
122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return sb.toString();
123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the maximum number of registers that may be in this instance, which
127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * is also the maximum-plus-one of register numbers that may be
128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * represented.
129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code >= 0;} the maximum size
131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public int getMaxSize() {
133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return specs.length;
134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the current size of this instance.
138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code >= 0;} the size
140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public int size() {
142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int result = size;
143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (result < 0) {
145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            int len = specs.length;
146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result = 0;
148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            for (int i = 0; i < len; i++) {
149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                if (specs[i] != null) {
150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    result++;
151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                }
152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            size = result;
155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return result;
158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the element with the given register number, if any.
162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param reg {@code >= 0;} the desired register number
164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code null-ok;} the element with the given register number or
165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code null} if there is none
166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public RegisterSpec get(int reg) {
168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        try {
169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            return specs[reg];
170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } catch (ArrayIndexOutOfBoundsException ex) {
171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            // Translate the exception.
172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new IllegalArgumentException("bogus reg");
173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Gets the element with the same register number as the given
178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * spec, if any. This is just a convenient shorthand for
179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code get(spec.getReg())}.
180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param spec {@code non-null;} spec with the desired register number
182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code null-ok;} the element with the matching register number or
183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@code null} if there is none
184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public RegisterSpec get(RegisterSpec spec) {
186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return get(spec.getReg());
187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns the spec in this set that's currently associated with a
191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * given local (type, name, and signature), or {@code null} if there is
192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * none. This ignores the register number of the given spec but
193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * matches on everything else.
194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param spec {@code non-null;} local to look for
196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code null-ok;} first register found that matches, if any
197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public RegisterSpec findMatchingLocal(RegisterSpec spec) {
199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int length = specs.length;
200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int reg = 0; reg < length; reg++) {
202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            RegisterSpec s = specs[reg];
203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (s == null) {
205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                continue;
206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (spec.matchesVariable(s)) {
209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                return s;
210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return null;
214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns the spec in this set that's currently associated with a given
218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * local (name and signature), or {@code null} if there is none.
219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param local {@code non-null;} local item to search for
221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code null-ok;} first register found with matching name and signature
222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public RegisterSpec localItemToSpec(LocalItem local) {
224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int length = specs.length;
225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int reg = 0; reg < length; reg++) {
227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            RegisterSpec spec = specs[reg];
228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if ((spec != null) && local.equals(spec.getLocalItem())) {
230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                return spec;
231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return null;
235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Removes a spec from the set. Only the register number
239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * of the parameter is significant.
240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param toRemove {@code non-null;} register to remove.
242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void remove(RegisterSpec toRemove) {
244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        try {
245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            specs[toRemove.getReg()] = null;
246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            size = -1;
247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } catch (ArrayIndexOutOfBoundsException ex) {
248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            // Translate the exception.
249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new IllegalArgumentException("bogus reg");
250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Puts the given spec into the set. If there is already an element in
255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * the set with the same register number, it is replaced. Additionally,
256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * if the previous element is for a category-2 register, then that
257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * previous element is nullified. Finally, if the given spec is for
258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * a category-2 register, then the immediately subsequent element
259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * is nullified.
260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param spec {@code non-null;} the register spec to put in the instance
262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void put(RegisterSpec spec) {
264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        throwIfImmutable();
265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (spec == null) {
267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new NullPointerException("spec == null");
268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        size = -1;
271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        try {
273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            int reg = spec.getReg();
274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            specs[reg] = spec;
275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (reg > 0) {
277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                int prevReg = reg - 1;
278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                RegisterSpec prevSpec = specs[prevReg];
279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                if ((prevSpec != null) && (prevSpec.getCategory() == 2)) {
280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                    specs[prevReg] = null;
281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                }
282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (spec.getCategory() == 2) {
285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                specs[reg + 1] = null;
286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        } catch (ArrayIndexOutOfBoundsException ex) {
288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            // Translate the exception.
289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            throw new IllegalArgumentException("spec.getReg() out of range");
290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Put the entire contents of the given set into this one.
295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param set {@code non-null;} the set to put into this instance
297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void putAll(RegisterSpecSet set) {
299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int max = set.getMaxSize();
300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < max; i++) {
302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            RegisterSpec spec = set.get(i);
303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (spec != null) {
304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                put(spec);
305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Intersects this instance with the given one, modifying this
311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * instance. The intersection consists of the pairwise
312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * {@link RegisterSpec#intersect} of corresponding elements from
313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * this instance and the given one where both are non-null.
314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param other {@code non-null;} set to intersect with
316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param localPrimary whether local variables are primary to
317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * the intersection; if {@code true}, then the only non-null
318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * result elements occur when registers being intersected have
319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * equal names (or both have {@code null} names)
320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public void intersect(RegisterSpecSet other, boolean localPrimary) {
322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        throwIfImmutable();
323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        RegisterSpec[] otherSpecs = other.specs;
325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int thisLen = specs.length;
326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int len = Math.min(thisLen, otherSpecs.length);
327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        size = -1;
329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < len; i++) {
331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            RegisterSpec spec = specs[i];
332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (spec == null) {
334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                continue;
335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            RegisterSpec intersection =
338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                spec.intersect(otherSpecs[i], localPrimary);
339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (intersection != spec) {
340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                specs[i] = intersection;
341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = len; i < thisLen; i++) {
345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            specs[i] = null;
346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Returns an instance that is identical to this one, except that
351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * all register numbers are offset by the given amount. Mutability
352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * of the result is inherited from the original.
353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @param delta the amount to offset the register numbers by
355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} an appropriately-constructed instance
356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public RegisterSpecSet withOffset(int delta) {
358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int len = specs.length;
359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        RegisterSpecSet result = new RegisterSpecSet(len + delta);
360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < len; i++) {
362917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            RegisterSpec spec = specs[i];
363917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (spec != null) {
364917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                result.put(spec.withOffset(delta));
365917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
366917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
367917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
368917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        result.size = size;
369917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
370917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        if (isImmutable()) {
371917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            result.setImmutable();
372917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
373917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
374917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return result;
375917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
376917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
377917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    /**
378917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * Makes and return a mutable copy of this instance.
379917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     *
380917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     * @return {@code non-null;} the mutable copy
381917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul     */
382917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    public RegisterSpecSet mutableCopy() {
383917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        int len = specs.length;
384917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        RegisterSpecSet copy = new RegisterSpecSet(len);
385917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
386917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        for (int i = 0; i < len; i++) {
387917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            RegisterSpec spec = specs[i];
388917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            if (spec != null) {
389917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul                copy.put(spec);
390917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul            }
391917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        }
392917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
393917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        copy.size = size;
394917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul
395917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul        return copy;
396917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul    }
397917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul}
398