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.dex.code;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.RegisterSpec;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.RegisterSpecSet;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstType;
22333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilsonimport com.android.dx.rop.cst.CstString;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.FixedSizeList;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.PrintStream;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Arrays;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * List of local variables. Each local variable entry indicates a
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * range of code which it is valid for, a register number, a name,
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and a type.
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class LocalList extends FixedSizeList {
3699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} empty instance */
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final LocalList EMPTY = new LocalList(0);
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** whether to run the self-check code */
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final boolean DEBUG = false;
41f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
4399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Constructs an instance. All indices initially contain {@code null}.
44f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein     *
4599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param size {@code >= 0;} the size of the list
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public LocalList(int size) {
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super(size);
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the element at the given index. It is an error to call
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this with the index for an element which was never set; if you
5499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * do that, this will throw {@code NullPointerException}.
55f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein     *
5699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param n {@code >= 0, < size();} which index
5799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} element at that index
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Entry get(int n) {
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (Entry) get0(n);
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Sets the entry at the given index.
65f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein     *
6699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param n {@code >= 0, < size();} which index
6799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param entry {@code non-null;} the entry to set at {@code n}
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void set(int n, Entry entry) {
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        set0(n, entry);
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Does a human-friendly dump of this instance.
75f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein     *
7699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param out {@code non-null;} where to dump
7799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param prefix {@code non-null;} prefix to attach to each line of output
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void debugPrint(PrintStream out, String prefix) {
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int sz = size();
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < sz; i++) {
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.print(prefix);
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            out.println(get(i));
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Disposition of a local entry.
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static enum Disposition {
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** local started (introduced) */
93f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        START,
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** local ended without being replaced */
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        END_SIMPLY,
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** local ended because it was directly replaced */
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        END_REPLACED,
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** local ended because it was moved to a different register */
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        END_MOVED,
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * local ended because the previous local clobbered this one
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * (because it is category-2)
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        END_CLOBBERED_BY_PREV,
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * local ended because the next local clobbered this one
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * (because this one is a category-2)
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        END_CLOBBERED_BY_NEXT;
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Entry in a local list.
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static class Entry implements Comparable<Entry> {
12199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /** {@code >= 0;} address */
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private final int address;
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
12499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /** {@code non-null;} disposition of the local */
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private final Disposition disposition;
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
12799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /** {@code non-null;} register spec representing the variable */
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private final RegisterSpec spec;
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
13099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /** {@code non-null;} variable type (derived from {@code spec}) */
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private final CstType type;
132f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Constructs an instance.
135f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
136f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         * @param address {@code >= 0;} address
13799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param disposition {@code non-null;} disposition of the local
1384b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein         * @param spec {@code non-null;} register spec representing
1394b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein         * the variable
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public Entry(int address, Disposition disposition, RegisterSpec spec) {
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (address < 0) {
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new IllegalArgumentException("address < 0");
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (disposition == null) {
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new NullPointerException("disposition == null");
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            try {
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (spec.getLocalItem() == null) {
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    throw new NullPointerException(
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "spec.getLocalItem() == null");
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } catch (NullPointerException ex) {
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Elucidate the exception.
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new NullPointerException("spec == null");
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.address = address;
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.disposition = disposition;
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.spec = spec;
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.type = CstType.intern(spec.getType());
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** {@inheritDoc} */
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public String toString() {
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return Integer.toHexString(address) + " " + disposition + " " +
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                spec;
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** {@inheritDoc} */
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public boolean equals(Object other) {
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!(other instanceof Entry)) {
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return (compareTo((Entry) other) == 0);
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Compares by (in priority order) address, end then start
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * disposition (variants of end are all consistered
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * equivalent), and spec.
185f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
18699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param other {@code non-null;} entry to compare to
18799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code -1..1;} standard result of comparison
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int compareTo(Entry other) {
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (address < other.address) {
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return -1;
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (address > other.address) {
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return 1;
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean thisIsStart = isStart();
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean otherIsStart = other.isStart();
198f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (thisIsStart != otherIsStart) {
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return thisIsStart ? 1 : -1;
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return spec.compareTo(other.spec);
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Gets the address.
208f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
20999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code >= 0;} the address
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int getAddress() {
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return address;
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Gets the disposition.
217f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
21899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code non-null;} the disposition
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public Disposition getDisposition() {
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return disposition;
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Gets whether this is a local start. This is just shorthand for
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * {@code getDisposition() == Disposition.START}.
227f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * @return {@code true} iff this is a start
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public boolean isStart() {
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return disposition == Disposition.START;
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Gets the variable name.
236f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
23799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code null-ok;} the variable name
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
239333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson        public CstString getName() {
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return spec.getLocalItem().getName();
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Gets the variable signature.
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
24699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code null-ok;} the variable signature
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
248333201833d506a3accdeac6ceb7caba8d4b95797Jesse Wilson        public CstString getSignature() {
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return spec.getLocalItem().getSignature();
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Gets the variable's type.
254f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
25599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code non-null;} the type
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public CstType getType() {
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return type;
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Gets the number of the register holding the variable.
263f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
2644b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein         * @return {@code >= 0;} the number of the register holding
2654b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein         * the variable
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int getRegister() {
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return spec.getReg();
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Gets the RegisterSpec of the register holding the variable.
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
27499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code non-null;} RegisterSpec of the holding register.
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public RegisterSpec getRegisterSpec() {
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return spec;
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Returns whether or not this instance matches the given spec.
282f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
28392f4f58df944fd10c77e3d39d200c38c1491a941Jean-Baptiste Queru         * @param otherSpec {@code non-null;} the spec in question
28499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code true} iff this instance matches
28599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * {@code spec}
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public boolean matches(RegisterSpec otherSpec) {
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return spec.equalsUsingSimpleType(otherSpec);
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Returns whether or not this instance matches the spec in
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the given instance.
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
29599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param other {@code non-null;} another entry
29699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code true} iff this instance's spec matches
29799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * {@code other}
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public boolean matches(Entry other) {
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return matches(other.spec);
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Returns an instance just like this one but with the disposition
305f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         * set as given.
306f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
30799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param disposition {@code non-null;} the new disposition
30899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code non-null;} an appropriately-constructed instance
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public Entry withDisposition(Disposition disposition) {
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (disposition == this.disposition) {
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return this;
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
314f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return new Entry(address, disposition, spec);
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
318f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance for the given method, based on the given
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * block order and intermediate local information.
322f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein     *
32399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param insns {@code non-null;} instructions to convert
324f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein     * @return {@code non-null;} the constructed list
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static LocalList make(DalvInsnList insns) {
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int sz = insns.size();
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Go through the insn list, looking for all the local
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * variable pseudoinstructions, splitting out LocalSnapshots
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * into separate per-variable starts, adding explicit ends
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * wherever a variable is replaced or moved, and collecting
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * these and all the other local variable "activity"
335f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         * together into an output list (without the other insns).
336f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Note: As of this writing, this method won't be handed any
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * insn lists that contain local ends, but I (danfuzz) expect
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * that to change at some point, when we start feeding that
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * info explicitly into the rop layer rather than only trying
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * to infer it. So, given that expectation, this code is
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * written to deal with them.
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        MakeState state = new MakeState(sz);
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < sz; i++) {
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            DalvInsn insn = insns.get(i);
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (insn instanceof LocalSnapshot) {
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpecSet snapshot =
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    ((LocalSnapshot) insn).getLocals();
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                state.snapshot(insn.getAddress(), snapshot);
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (insn instanceof LocalStart) {
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec local = ((LocalStart) insn).getLocal();
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                state.startLocal(insn.getAddress(), local);
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (insn instanceof LocalEnd) {
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec local = ((LocalEnd) insn).getLocal();
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                state.endLocal(insn.getAddress(), local);
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LocalList result = state.finish();
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (DEBUG) {
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            debugVerify(result);
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Debugging helper that verifies the constraint that a list doesn't
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * contain any redundant local starts and that local ends that are
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * due to replacements are properly annotated.
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static void debugVerify(LocalList locals) {
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            debugVerify0(locals);
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (RuntimeException ex) {
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int sz = locals.size();
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < sz; i++) {
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                System.err.println(locals.get(i));
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw ex;
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
387f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
389f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper for {@link #debugVerify} which does most of the work.
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static void debugVerify0(LocalList locals) {
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int sz = locals.size();
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Entry[] active = new Entry[65536];
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < sz; i++) {
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Entry e = locals.get(i);
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int reg = e.getRegister();
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (e.isStart()) {
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Entry already = active[reg];
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if ((already != null) && e.matches(already)) {
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    throw new RuntimeException("redundant start at " +
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            Integer.toHexString(e.getAddress()) + ": got " +
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            e + "; had " + already);
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                active[reg] = e;
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (active[reg] == null) {
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    throw new RuntimeException("redundant end at " +
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            Integer.toHexString(e.getAddress()));
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
416f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int addr = e.getAddress();
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                boolean foundStart = false;
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                for (int j = i + 1; j < sz; j++) {
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    Entry test = locals.get(j);
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (test.getAddress() != addr) {
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        break;
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (test.getRegisterSpec().getReg() == reg) {
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        if (test.isStart()) {
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            if (e.getDisposition()
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    != Disposition.END_REPLACED) {
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                throw new RuntimeException(
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                        "improperly marked end at " +
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                        Integer.toHexString(addr));
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            }
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            foundStart = true;
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        } else {
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            throw new RuntimeException(
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    "redundant end at " +
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    Integer.toHexString(addr));
438f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                        }
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!foundStart &&
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        (e.getDisposition() == Disposition.END_REPLACED)) {
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    throw new RuntimeException(
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            "improper end replacement claim at " +
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            Integer.toHexString(addr));
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
448f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                active[reg] = null;
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Intermediate state when constructing a local list.
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static class MakeState {
45899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /** {@code non-null;} result being collected */
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private final ArrayList<Entry> result;
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
46299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * {@code >= 0;} running count of nulled result entries, to help with
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * sizing the final list
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private int nullResultCount;
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
46799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /** {@code null-ok;} current register mappings */
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private RegisterSpecSet regs;
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
47099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /** {@code null-ok;} result indices where local ends are stored */
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private int[] endIndices;
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
47399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /** {@code >= 0;} last address seen */
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private int lastAddress;
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Constructs an instance.
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public MakeState(int initialSize) {
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result = new ArrayList<Entry>(initialSize);
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nullResultCount = 0;
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regs = null;
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            endIndices = null;
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            lastAddress = 0;
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Checks the address and other vitals as a prerequisite to
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * further processing.
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
49199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param address {@code >= 0;} address about to be processed
49299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param reg {@code >= 0;} register number about to be processed
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void aboutToProcess(int address, int reg) {
495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean first = (endIndices == null);
496f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((address == lastAddress) && !first) {
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return;
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (address < lastAddress) {
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new RuntimeException("shouldn't happen");
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (first || (reg >= endIndices.length)) {
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * This is the first allocation of the state set and
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * index array, or we need to grow. (The latter doesn't
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * happen much; in fact, we have only ever observed
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * it happening in test cases, never in "real" code.)
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int newSz = reg + 1;
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpecSet newRegs = new RegisterSpecSet(newSz);
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int[] newEnds = new int[newSz];
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Arrays.fill(newEnds, -1);
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!first) {
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    newRegs.putAll(regs);
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    System.arraycopy(endIndices, 0, newEnds, 0,
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            endIndices.length);
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                regs = newRegs;
524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                endIndices = newEnds;
525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Sets the local state at the given address to the given snapshot.
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The first call on this instance must be to this method, so that
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * the register state can be properly sized.
532f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
53399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param address {@code >= 0;} the address
53499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param specs {@code non-null;} spec set representing the locals
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public void snapshot(int address, RegisterSpecSet specs) {
537f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            if (DEBUG) {
538f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                System.err.printf("%04x snapshot %s\n", address, specs);
539f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            }
540f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int sz = specs.getMaxSize();
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            aboutToProcess(address, sz - 1);
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < sz; i++) {
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec oldSpec = regs.get(i);
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec newSpec = filterSpec(specs.get(i));
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (oldSpec == null) {
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (newSpec != null) {
550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        startLocal(address, newSpec);
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else if (newSpec == null) {
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    endLocal(address, oldSpec);
554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } else if (! newSpec.equalsUsingSimpleType(oldSpec)) {
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    endLocal(address, oldSpec);
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    startLocal(address, newSpec);
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
559f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
560f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            if (DEBUG) {
561f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                System.err.printf("%04x snapshot done\n", address);
562f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            }
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
564f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Starts a local at the given address.
567f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
56899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param address {@code >= 0;} the address
5694b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein         * @param startedLocal {@code non-null;} spec representing the
5704b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein         * started local
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public void startLocal(int address, RegisterSpec startedLocal) {
573f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            if (DEBUG) {
574f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                System.err.printf("%04x start %s\n", address, startedLocal);
575f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            }
576f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int regNum = startedLocal.getReg();
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            startedLocal = filterSpec(startedLocal);
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            aboutToProcess(address, regNum);
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegisterSpec existingLocal = regs.get(regNum);
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (startedLocal.equalsUsingSimpleType(existingLocal)) {
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Silently ignore a redundant start.
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return;
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegisterSpec movedLocal = regs.findMatchingLocal(startedLocal);
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (movedLocal != null) {
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * The same variable was moved from one register to another.
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * So add an end for its old location.
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                addOrUpdateEnd(address, Disposition.END_MOVED, movedLocal);
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int endAt = endIndices[regNum];
599f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (existingLocal != null) {
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * There is an existing (but non-matching) local.
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * Add an explicit end for it.
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                add(address, Disposition.END_REPLACED, existingLocal);
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else if (endAt >= 0) {
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * Look for an end local for the same register at the
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * same address. If found, then update it or delete
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * it, depending on whether or not it represents the
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * same variable as the one being started.
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Entry endEntry = result.get(endAt);
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (endEntry.getAddress() == address) {
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (endEntry.matches(startedLocal)) {
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        /*
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * There was already an end local for the same
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * variable at the same address. This turns
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * out to be superfluous, as we are starting
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * up the exact same local. This situation can
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * happen when a single local variable got
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * somehow "split up" during intermediate
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * processing. In any case, rather than represent
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * the end-then-start, just remove the old end.
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         */
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        result.set(endAt, null);
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        nullResultCount++;
628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        regs.put(startedLocal);
629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        endIndices[regNum] = -1;
630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        return;
631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } else {
632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        /*
633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * There was a different variable ended at the
634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * same address. Update it to indicate that
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * it was ended due to a replacement (rather than
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         * ending for no particular reason).
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         */
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        endEntry = endEntry.withDisposition(
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                Disposition.END_REPLACED);
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        result.set(endAt, endEntry);
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
644f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
645f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            /*
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * The code above didn't find and remove an unnecessary
647f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * local end, so we now have to add one or more entries to
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * the output to capture the transition.
649f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
650f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
651f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * If the local just below (in the register set at reg-1)
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * is of category-2, then it is ended by this new start.
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (regNum > 0) {
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec justBelow = regs.get(regNum - 1);
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if ((justBelow != null) && justBelow.isCategory2()) {
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    addOrUpdateEnd(address,
659f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            Disposition.END_CLOBBERED_BY_NEXT,
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            justBelow);
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Similarly, if this local is category-2, then the local
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * just above (if any) is ended by the start now being
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * emitted.
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (startedLocal.isCategory2()) {
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec justAbove = regs.get(regNum + 1);
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (justAbove != null) {
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    addOrUpdateEnd(address,
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            Disposition.END_CLOBBERED_BY_PREV,
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            justAbove);
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * TODO: Add an end for the same local in a different reg,
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * if any (that is, if the local migrates from vX to vY,
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * we should note that as a local end in vX).
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
683f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            add(address, Disposition.START, startedLocal);
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
688f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         * Ends a local at the given address, using the disposition
689f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         * {@code END_SIMPLY}.
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
69199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param address {@code >= 0;} the address
6924b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein         * @param endedLocal {@code non-null;} spec representing the
6934b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein         * local being ended
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public void endLocal(int address, RegisterSpec endedLocal) {
696f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            endLocal(address, endedLocal, Disposition.END_SIMPLY);
697f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        }
698f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
699f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        /**
700f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         * Ends a local at the given address.
701f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
702f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         * @param address {@code >= 0;} the address
703f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         * @param endedLocal {@code non-null;} spec representing the
704f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         * local being ended
705f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         * @param disposition reason for the end
706f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         */
707f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein        public void endLocal(int address, RegisterSpec endedLocal,
708f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                Disposition disposition) {
709f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            if (DEBUG) {
710f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                System.err.printf("%04x end %s\n", address, endedLocal);
711f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            }
712f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int regNum = endedLocal.getReg();
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            endedLocal = filterSpec(endedLocal);
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            aboutToProcess(address, regNum);
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int endAt = endIndices[regNum];
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (endAt >= 0) {
721f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
722f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * The local in the given register is already ended.
723f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * Silently return without adding anything to the result.
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return;
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Check for start and end at the same address.
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (checkForEmptyRange(address, endedLocal)) {
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return;
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
733f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            add(address, disposition, endedLocal);
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Helper for {@link #endLocal}, which handles the cases where
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and end local is issued at the same address as a start local
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * for the same register. If this case is found, then this
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * method will remove the start (as the local was never actually
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * active), update the {@link #endIndices} to be accurate, and
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * if needed update the newly-active end to reflect an altered
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * disposition.
744f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
74599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param address {@code >= 0;} the address
7464b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein         * @param endedLocal {@code non-null;} spec representing the
7474b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein         * local being ended
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * @return {@code true} iff this method found the case in question
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * and adjusted things accordingly
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private boolean checkForEmptyRange(int address,
752f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec endedLocal) {
753f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int at = result.size() - 1;
754f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Entry entry;
755f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Look for a previous entry at the same address.
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (/*at*/; at >= 0; at--) {
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                entry = result.get(at);
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (entry == null) {
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    continue;
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (entry.getAddress() != address) {
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // We didn't find any match at the same address.
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return false;
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (entry.matches(endedLocal)) {
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * In fact, we found that the endedLocal had started at the
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * same address, so do all the requisite cleanup.
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
778f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            regs.remove(endedLocal);
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.set(at, null);
781f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            nullResultCount++;
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int regNum = endedLocal.getReg();
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean found = false;
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            entry = null;
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Now look back further to update where the register ended.
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (at--; at >= 0; at--) {
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                entry = result.get(at);
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (entry == null) {
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    continue;
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (entry.getRegisterSpec().getReg() == regNum) {
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    found = true;
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (found) {
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // We found an end for the same register.
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                endIndices[regNum] = at;
804f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (entry.getAddress() == address) {
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /*
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * It's still the same address, so update the
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * disposition.
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result.set(at,
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            entry.withDisposition(Disposition.END_SIMPLY));
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Converts a given spec into the form acceptable for use in a
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * local list. This, in particular, transforms the "known
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * null" type into simply {@code Object}. This method needs to
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * be called for any spec that is on its way into a locals
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * list.
824f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * <p>This isn't necessarily the cleanest way to achieve the
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * goal of not representing known nulls in a locals list, but
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * it gets the job done.</p>
828f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
82999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param orig {@code null-ok;} the original spec
83099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code null-ok;} an appropriately modified spec, or the
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * original if nothing needs to be done
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private static RegisterSpec filterSpec(RegisterSpec orig) {
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((orig != null) && (orig.getType() == Type.KNOWN_NULL)) {
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return orig.withType(Type.OBJECT);
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return orig;
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Adds an entry to the result, updating the adjunct tables
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * accordingly.
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
84599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param address {@code >= 0;} the address
84699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param disposition {@code non-null;} the disposition
84799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param spec {@code non-null;} spec representing the local
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void add(int address, Disposition disposition,
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec spec) {
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int regNum = spec.getReg();
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result.add(new Entry(address, disposition, spec));
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (disposition == Disposition.START) {
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                regs.put(spec);
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                endIndices[regNum] = -1;
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                regs.remove(spec);
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                endIndices[regNum] = result.size() - 1;
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
865f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         * Adds or updates an end local (changing its disposition). If
866f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         * this would cause an empty range for a local, this instead
867f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         * removes the local entirely.
868f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
86999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param address {@code >= 0;} the address
87099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param disposition {@code non-null;} the disposition
87199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @param spec {@code non-null;} spec representing the local
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private void addOrUpdateEnd(int address, Disposition disposition,
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec spec) {
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (disposition == Disposition.START) {
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new RuntimeException("shouldn't happen");
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int regNum = spec.getReg();
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int endAt = endIndices[regNum];
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (endAt >= 0) {
883f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                // There is a previous end.
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                Entry endEntry = result.get(endAt);
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if ((endEntry.getAddress() == address) &&
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        endEntry.getRegisterSpec().equals(spec)) {
887f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                    /*
888f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                     * The end is for the right address and variable, so
889f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                     * update it.
890f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                     */
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    result.set(endAt, endEntry.withDisposition(disposition));
892f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein                    regs.remove(spec); // TODO: Is this line superfluous?
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return;
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
896f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
897f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein            endLocal(address, spec, disposition);
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Finishes processing altogether and gets the result.
902f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein         *
90399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code non-null;} the result list
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public LocalList finish() {
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            aboutToProcess(Integer.MAX_VALUE, 0);
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int resultSz = result.size();
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int finalSz = resultSz - nullResultCount;
910f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (finalSz == 0) {
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return EMPTY;
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Collect an array of only the non-null entries, and then
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * sort it to get a consistent order for everything: Local
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * ends and starts for a given address could come in any
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * order, but we want ends before starts as well as
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * registers in order (within ends or starts).
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Entry[] resultArr = new Entry[finalSz];
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (resultSz == finalSz) {
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                result.toArray(resultArr);
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int at = 0;
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                for (Entry e : result) {
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (e != null) {
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        resultArr[at++] = e;
932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Arrays.sort(resultArr);
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LocalList resultList = new LocalList(finalSz);
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < finalSz; i++) {
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                resultList.set(i, resultArr[i]);
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            resultList.setImmutable();
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return resultList;
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
947f58a5f30d1f0613e9e2dd3a24e6057f970258daeDan Bornstein    }
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
949