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.cf.code;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.LocalItem;
20fe107fb6e3f308ac5174ebdc5a794ee880c741d9Jesse Wilsonimport com.android.dx.rop.code.RegisterSpec;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.Constant;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Prototype;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.StdTypeList;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.TypeBearer;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Base implementation of {@link Machine}.
30de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro *
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p><b>Note:</b> For the most part, the documentation for this class
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ignores the distinction between {@link Type} and {@link
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TypeBearer}.</p>
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic abstract class BaseMachine implements Machine {
3699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /* {@code non-null;} the prototype for the associated method */
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final Prototype prototype;
38de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
3999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} primary arguments */
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private TypeBearer[] args;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code >= 0;} number of primary arguments */
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int argCount;
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code null-ok;} type of the operation, if salient */
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private Type auxType;
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** auxiliary {@code int} argument */
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int auxInt;
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code null-ok;} auxiliary constant argument */
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private Constant auxCst;
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** auxiliary branch target argument */
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int auxTarget;
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code null-ok;} auxiliary switch cases argument */
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private SwitchList auxCases;
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code null-ok;} auxiliary initial value list for newarray */
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private ArrayList<Constant> auxInitValues;
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code >= -1;} last local accessed */
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int localIndex;
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
66c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao    /** specifies if local has info in the local variable table */
67c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao    private boolean localInfo;
68c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao
6999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code null-ok;} local target spec, if salient and calculated */
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private RegisterSpec localTarget;
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} results */
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private TypeBearer[] results;
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
7699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code >= -1;} count of the results, or {@code -1} if no results
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * have been set
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int resultCount;
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance.
83de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
843d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein     * @param prototype {@code non-null;} the prototype for the
853d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein     * associated method
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public BaseMachine(Prototype prototype) {
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (prototype == null) {
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("prototype == null");
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.prototype = prototype;
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        args = new TypeBearer[10];
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        results = new TypeBearer[6];
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clearArgs();
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Prototype getPrototype() {
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return prototype;
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void clearArgs() {
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        argCount = 0;
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        auxType = null;
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        auxInt = 0;
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        auxCst = null;
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        auxTarget = 0;
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        auxCases = null;
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        auxInitValues = null;
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        localIndex = -1;
113c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao        localInfo = false;
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        localTarget = null;
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resultCount = -1;
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void popArgs(Frame frame, int count) {
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ExecutionStack stack = frame.getStack();
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clearArgs();
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (count > args.length) {
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Grow args, and add a little extra room to grow even more.
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            args = new TypeBearer[count + 10];
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = count - 1; i >= 0; i--) {
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            args[i] = stack.pop();
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        argCount = count;
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void popArgs(Frame frame, Prototype prototype) {
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StdTypeList types = prototype.getParameterTypes();
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int size = types.size();
140de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Use the above method to do the actual popping...
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        popArgs(frame, size);
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // ...and then verify the popped types.
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < size; i++) {
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (! Merger.isPossiblyAssignableFrom(types.getType(i), args[i])) {
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new SimException("at stack depth " + (size - 1 - i) +
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        ", expected type " + types.getType(i).toHuman() +
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        " but found " + args[i].getType().toHuman());
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void popArgs(Frame frame, Type type) {
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Use the above method to do the actual popping...
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        popArgs(frame, 1);
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // ...and then verify the popped type.
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (! Merger.isPossiblyAssignableFrom(type, args[0])) {
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new SimException("expected type " + type.toHuman() +
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    " but found " + args[0].getType().toHuman());
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void popArgs(Frame frame, Type type1, Type type2) {
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Use the above method to do the actual popping...
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        popArgs(frame, 2);
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // ...and then verify the popped types.
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (! Merger.isPossiblyAssignableFrom(type1, args[0])) {
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new SimException("expected type " + type1.toHuman() +
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    " but found " + args[0].getType().toHuman());
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (! Merger.isPossiblyAssignableFrom(type2, args[1])) {
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new SimException("expected type " + type2.toHuman() +
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    " but found " + args[1].getType().toHuman());
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void popArgs(Frame frame, Type type1, Type type2,
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Type type3) {
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // Use the above method to do the actual popping...
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        popArgs(frame, 3);
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // ...and then verify the popped types.
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (! Merger.isPossiblyAssignableFrom(type1, args[0])) {
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new SimException("expected type " + type1.toHuman() +
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    " but found " + args[0].getType().toHuman());
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (! Merger.isPossiblyAssignableFrom(type2, args[1])) {
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new SimException("expected type " + type2.toHuman() +
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    " but found " + args[1].getType().toHuman());
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (! Merger.isPossiblyAssignableFrom(type3, args[2])) {
203c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao            throw new SimException("expected type " + type3.toHuman() +
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    " but found " + args[2].getType().toHuman());
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void localArg(Frame frame, int idx) {
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        clearArgs();
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        args[0] = frame.getLocals().get(idx);
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        argCount = 1;
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        localIndex = idx;
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
217c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao    public final void localInfo(boolean local) {
218c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao        localInfo = local;
219c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao    }
220c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao
221c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao    /** {@inheritDoc} */
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void auxType(Type type) {
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        auxType = type;
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void auxIntArg(int value) {
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        auxInt = value;
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void auxCstArg(Constant cst) {
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cst == null) {
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("cst == null");
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        auxCst = cst;
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void auxTargetArg(int target) {
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        auxTarget = target;
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void auxSwitchArg(SwitchList cases) {
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cases == null) {
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("cases == null");
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        auxCases = cases;
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void auxInitValues(ArrayList<Constant> initValues) {
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        auxInitValues = initValues;
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void localTarget(int idx, Type type, LocalItem local) {
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        localTarget = RegisterSpec.makeLocalOptional(idx, type, local);
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the number of primary arguments.
266de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
26799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= 0;} the number of primary arguments
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final int argCount() {
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return argCount;
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the width of the arguments (where a category-2 value counts as
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * two).
276de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
27799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= 0;} the argument width
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final int argWidth() {
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int result = 0;
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < argCount; i++) {
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            result += args[i].getType().getCategory();
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return result;
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
29099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets the {@code n}th primary argument.
291de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
29299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param n {@code >= 0, < argCount();} which argument
29399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the indicated argument
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final TypeBearer arg(int n) {
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (n >= argCount) {
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("n >= argCount");
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return args[n];
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (ArrayIndexOutOfBoundsException ex) {
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Translate the exception.
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("n < 0");
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the type auxiliary argument.
310de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
31199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code null-ok;} the salient type
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final Type getAuxType() {
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return auxType;
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
31899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets the {@code int} auxiliary argument.
319de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the argument value
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final int getAuxInt() {
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return auxInt;
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the constant auxiliary argument.
328de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
32999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code null-ok;} the argument value
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final Constant getAuxCst() {
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return auxCst;
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the branch target auxiliary argument.
337de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the argument value
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final int getAuxTarget() {
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return auxTarget;
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the switch cases auxiliary argument.
346de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
34799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code null-ok;} the argument value
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final SwitchList getAuxCases() {
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return auxCases;
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the init values auxiliary argument.
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
35699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code null-ok;} the argument value
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final ArrayList<Constant> getInitValues() {
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return auxInitValues;
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the last local index accessed.
363de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
36499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= -1;} the salient local index or {@code -1} if none
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * was set since the last time {@link #clearArgs} was called
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final int getLocalIndex() {
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return localIndex;
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
372c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao     * Gets whether the loaded local has info in the local variable table.
373c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao     *
374c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao     * @return {@code true} if local arg has info in the local variable table
375c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao     */
376c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao    protected final boolean getLocalInfo() {
377c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao        return localInfo;
378c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao    }
379c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao
380c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao    /**
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the target local register spec of the current operation, if any.
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The local target spec is the combination of the values indicated
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * by a previous call to {@link #localTarget} with the type of what
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * should be the sole result set by a call to {@link #setResult} (or
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the combination {@link #clearResult} then {@link #addResult}.
386de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
3873d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein     * @param isMove {@code true} if the operation being performed on the
3883d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein     * local is a move. This will cause constant values to be propagated
3893d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein     * to the returned local
39099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code null-ok;} the salient register spec or {@code null} if no
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * local target was set since the last time {@link #clearArgs} was
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * called
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3943d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein    protected final RegisterSpec getLocalTarget(boolean isMove) {
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (localTarget == null) {
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resultCount != 1) {
400de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro            throw new SimException("local target with " +
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    ((resultCount == 0) ? "no" : "multiple") + " results");
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TypeBearer result = results[0];
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Type resultType = result.getType();
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Type localType = localTarget.getType();
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resultType == localType) {
4093d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein            /*
4103d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein             * If this is to be a move operation and the result is a
4113d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein             * known value, make the returned localTarget embody that
4123d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein             * value.
4133d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein             */
4143d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein            if (isMove) {
4153d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein                return localTarget.withType(result);
4163d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein            } else {
4173d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein                return localTarget;
4183d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein            }
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (! Merger.isPossiblyAssignableFrom(localType, resultType)) {
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // The result and local types are inconsistent. Complain!
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throwLocalMismatch(resultType, localType);
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (localType == Type.OBJECT) {
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * The result type is more specific than the local type,
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * so use that instead.
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            localTarget = localTarget.withType(result);
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return localTarget;
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Clears the results.
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final void clearResult() {
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resultCount = 0;
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Sets the results list to be the given single value.
447de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <p><b>Note:</b> If there is more than one result value, the
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * others may be added by using {@link #addResult}.</p>
450de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
45199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param result {@code non-null;} result value
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final void setResult(TypeBearer result) {
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result == null) {
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("result == null");
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        results[0] = result;
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resultCount = 1;
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Adds an additional element to the list of results.
464de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see #setResult
466de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
46799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param result {@code non-null;} result value
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final void addResult(TypeBearer result) {
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result == null) {
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("result == null");
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        results[resultCount] = result;
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        resultCount++;
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the count of results. This throws an exception if results were
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * never set. (Explicitly clearing the results counts as setting them.)
481de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
48299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= 0;} the count
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final int resultCount() {
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resultCount < 0) {
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new SimException("results never set");
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return resultCount;
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the width of the results (where a category-2 value counts as
494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * two).
495de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
49699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= 0;} the result width
497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final int resultWidth() {
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int width = 0;
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < resultCount; i++) {
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            width += results[i].getType().getCategory();
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return width;
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
50999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets the {@code n}th result value.
510de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
51199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param n {@code >= 0, < resultCount();} which result
51299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the indicated result value
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final TypeBearer result(int n) {
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (n >= resultCount) {
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("n >= resultCount");
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return results[n];
521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (ArrayIndexOutOfBoundsException ex) {
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Translate the exception.
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("n < 0");
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     * Stores the results of the latest operation into the given frame. If
529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * there is a local target (see {@link #localTarget}), then the sole
530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * result is stored to that target; otherwise any results are pushed
531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * onto the stack.
532de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
53399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param frame {@code non-null;} frame to operate on
534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final void storeResults(Frame frame) {
536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resultCount < 0) {
537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new SimException("results never set");
538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (resultCount == 0) {
541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Nothing to do.
542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (localTarget != null) {
546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Note: getLocalTarget() doesn't necessarily return
548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * localTarget directly.
549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
5503d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein            frame.getLocals().set(getLocalTarget(false));
551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ExecutionStack stack = frame.getStack();
553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < resultCount; i++) {
554c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao                if (localInfo) {
555c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao                    stack.setLocal();
556c31f795aef67a0d6af9abe4610db5ecae8d30c19jeffhao                }
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                stack.push(results[i]);
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Throws an exception that indicates a mismatch in local variable
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * types.
565de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
56699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param found {@code non-null;} the encountered type
56799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param local {@code non-null;} the local variable's claimed type
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static void throwLocalMismatch(TypeBearer found,
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            TypeBearer local) {
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throw new SimException("local variable type mismatch: " +
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "attempt to set or access a value of type " +
573de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro                found.toHuman() +
574de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro                " using a local variable of type " +
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                local.toHuman() +
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ". This is symptomatic of .class transformation tools " +
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "that ignore local variable information.");
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
580