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