RopperMachine.java revision 4596322b12a72cdeea8deba1242d9b74da5ba12a
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.FillArrayDataInsn;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.Insn;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.PlainCstInsn;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.PlainInsn;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.RegOps;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.RegisterSpec;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.RegisterSpecList;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.Rop;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.Rops;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.SourcePosition;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.SwitchInsn;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.ThrowingCstInsn;
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.ThrowingInsn;
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.code.TranslationAdvice;
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.Constant;
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstFieldRef;
354596322b12a72cdeea8deba1242d9b74da5ba12ajeffhaoimport com.android.dx.rop.cst.CstInteger;
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstMethodRef;
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstNat;
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstType;
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.cst.CstUtf8;
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type;
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.TypeBearer;
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.TypeList;
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.IntList;
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList;
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Machine implementation for use by {@link Ropper}.
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*package*/ final class RopperMachine extends ValueAwareMachine {
5199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} array reflection class */
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final CstType ARRAY_REFLECT_TYPE =
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        new CstType(Type.internClassName("java/lang/reflect/Array"));
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
5699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code non-null;} method constant for use in converting
57de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * {@code multianewarray} instructions
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final CstMethodRef MULTIANEWARRAY_METHOD =
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        new CstMethodRef(ARRAY_REFLECT_TYPE,
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                         new CstNat(new CstUtf8("newInstance"),
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    new CstUtf8("(Ljava/lang/Class;[I)" +
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                                "Ljava/lang/Object;")));
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} {@link Ropper} controlling this instance */
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final Ropper ropper;
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} method being converted */
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final ConcreteMethod method;
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} translation advice */
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final TranslationAdvice advice;
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** max locals of the method */
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int maxLocals;
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} instructions for the rop basic block in-progress */
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final ArrayList<Insn> insns;
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
8099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} catches for the block currently being processed */
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private TypeList catches;
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** whether the catches have been used in an instruction */
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private boolean catchesUsed;
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
8699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** whether the block contains a {@code return} */
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private boolean returns;
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** primary successor index */
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int primarySuccessorIndex;
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
9299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code >= 0;} number of extra basic blocks required */
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int extraBlockCount;
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** true if last processed block ends with a jsr or jsr_W*/
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private boolean hasJsr;
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** true if an exception can be thrown by the last block processed */
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private boolean blockCanThrow;
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If non-null, the ReturnAddress that was used by the terminating ret
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instruction. If null, there was no ret instruction encountered.
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private ReturnAddress returnAddress;
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
10999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code null-ok;} the appropriate {@code return} op or {@code null}
110de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * if it is not yet known
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private Rop returnOp;
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
11599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code null-ok;} the source position for the return block or {@code null}
116de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     * if it is not yet known
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private SourcePosition returnPosition;
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance.
122de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
12399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param ropper {@code non-null;} ropper controlling this instance
12499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param method {@code non-null;} method being converted
12599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param advice {@code non-null;} translation advice to use
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public RopperMachine(Ropper ropper, ConcreteMethod method,
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            TranslationAdvice advice) {
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super(method.getEffectiveDescriptor());
130de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ropper == null) {
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("ropper == null");
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (advice == null) {
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("advice == null");
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.ropper = ropper;
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.method = method;
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.advice = advice;
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.maxLocals = method.getMaxLocals();
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.insns = new ArrayList<Insn>(25);
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.catches = null;
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.catchesUsed = false;
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.returns = false;
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.primarySuccessorIndex = -1;
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.extraBlockCount = 0;
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.blockCanThrow = false;
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.returnOp = null;
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.returnPosition = null;
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the instructions array. It is shared and gets modified by
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * subsequent calls to this instance.
157de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
15899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the instructions array
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ArrayList<Insn> getInsns() {
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return insns;
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the return opcode encountered, if any.
166de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
16799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code null-ok;} the return opcode
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Rop getReturnOp() {
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return returnOp;
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the return position, if known.
175de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
17699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code null-ok;} the return position
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public SourcePosition getReturnPosition() {
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return returnPosition;
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets ready to start working on a new block. This will clear the
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@link #insns} list, set {@link #catches}, reset whether it has
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * been used, reset whether the block contains a
18699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code return}, and reset {@link #primarySuccessorIndex}.
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void startBlock(TypeList catches) {
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.catches = catches;
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        insns.clear();
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        catchesUsed = false;
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returns = false;
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        primarySuccessorIndex = 0;
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        extraBlockCount = 0;
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        blockCanThrow = false;
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        hasJsr = false;
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        returnAddress = null;
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets whether {@link #catches} was used. This indicates that the
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * last instruction in the block is one of the ones that can throw.
204de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
20599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return whether {@code catches} has been used
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean wereCatchesUsed() {
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return catchesUsed;
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets whether the block just processed ended with a
21399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code return}.
214de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return whether the block returns
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean returns() {
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return returns;
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the primary successor index. This is the index into the
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * successors list where the primary may be found or
22499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code -1} if there are successors but no primary
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * successor. This may return something other than
22699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code -1} in the case of an instruction with no
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * successors at all (primary or otherwise).
228de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
22999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= -1;} the primary successor index
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getPrimarySuccessorIndex() {
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return primarySuccessorIndex;
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets how many extra blocks will be needed to represent the
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * block currently being translated. Each extra block should consist
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of one instruction from the end of the original block.
239de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
24099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= 0;} the number of extra blocks needed
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getExtraBlockCount() {
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return extraBlockCount;
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return true if at least one of the insn processed since the last
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * call to startBlock() can throw.
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean canThrow() {
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return blockCanThrow;
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return true if a JSR has ben encountered since the last call to
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * startBlock()
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean hasJsr() {
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return hasJsr;
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
263d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein     * @return {@code true} if a {@code ret} has ben encountered since
264d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein     * the last call to {@code startBlock()}
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean hasRet() {
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return returnAddress != null;
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
271d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein     * @return {@code null-ok;} return address of a {@code ret}
272d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein     * instruction if encountered since last call to startBlock().
273d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein     * {@code null} if no ret instruction encountered.
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ReturnAddress getReturnAddress() {
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return returnAddress;
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void run(Frame frame, int offset, int opcode) {
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * This is the stack pointer after the opcode's arguments have been
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * popped.
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int stackPointer = maxLocals + frame.getStack().size();
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // The sources have to be retrieved before super.run() gets called.
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RegisterSpecList sources = getSources(opcode, stackPointer);
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int sourceCount = sources.size();
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super.run(frame, offset, opcode);
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        SourcePosition pos = method.makeSourcePosistion(offset);
2953d0823c03df73acc786940489dcdd5b8e0d7cefeDan Bornstein        RegisterSpec localTarget = getLocalTarget(opcode == ByteOps.ISTORE);
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int destCount = resultCount();
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RegisterSpec dest;
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (destCount == 0) {
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dest = null;
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (opcode) {
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case ByteOps.POP:
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case ByteOps.POP2: {
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    // These simply don't appear in the rop form.
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return;
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (localTarget != null) {
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dest = localTarget;
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (destCount == 1) {
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dest = RegisterSpec.make(stackPointer, result(0));
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * This clause only ever applies to the stack manipulation
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * ops that have results (that is, dup* and swap but not
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * pop*).
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             *
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * What we do is first move all the source registers into
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * the "temporary stack" area defined for the method, and
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * then move stuff back down onto the main "stack" in the
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * arrangement specified by the stack op pattern.
322de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro             *
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Note: This code ends up emitting a lot of what will
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * turn out to be superfluous moves (e.g., moving back and
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * forth to the same local when doing a dup); however,
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * that makes this code a bit easier (and goodness knows
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * it doesn't need any extra complexity), and all the SSA
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * stuff is going to want to deal with this sort of
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * superfluous assignment anyway, so it should be a wash
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * in the end.
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int scratchAt = ropper.getFirstTempStackReg();
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegisterSpec[] scratchRegs = new RegisterSpec[sourceCount];
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < sourceCount; i++) {
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec src = sources.get(i);
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                TypeBearer type = src.getTypeBearer();
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec scratch = src.withReg(scratchAt);
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                insns.add(new PlainInsn(Rops.opMove(type), pos, scratch, src));
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                scratchRegs[i] = scratch;
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                scratchAt += src.getCategory();
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int pattern = getAuxInt(); pattern != 0; pattern >>= 4) {
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int which = (pattern & 0x0f) - 1;
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec scratch = scratchRegs[which];
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                TypeBearer type = scratch.getTypeBearer();
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                insns.add(new PlainInsn(Rops.opMove(type), pos,
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                        scratch.withReg(stackPointer),
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                        scratch));
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                stackPointer += type.getType().getCategory();
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
354de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro        }
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        TypeBearer destType = (dest != null) ? dest : Type.VOID;
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Constant cst = getAuxCst();
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int ropOpcode;
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Rop rop;
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Insn insn;
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (opcode == ByteOps.MULTIANEWARRAY) {
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            blockCanThrow = true;
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Add the extra instructions for handling multianewarray.
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            extraBlockCount = 6;
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Add an array constructor for the int[] containing all the
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * dimensions.
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
373de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro            RegisterSpec dimsReg =
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec.make(dest.getNextReg(), Type.INT_ARRAY);
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            rop = Rops.opFilledNewArray(Type.INT_ARRAY, sourceCount);
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insn = new ThrowingCstInsn(rop, pos, sources, catches,
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CstType.INT_ARRAY);
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insns.add(insn);
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Add a move-result for the new-filled-array
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            rop = Rops.opMoveResult(Type.INT_ARRAY);
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insn = new PlainInsn(rop, pos, dimsReg, RegisterSpecList.EMPTY);
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insns.add(insn);
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Add a const-class instruction for the specified array
387de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro             * class.
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Remove as many dimensions from the originally specified
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * class as are given in the explicit list of dimensions,
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * so as to pass the right component class to the standard
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Java library array constructor.
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Type componentType = ((CstType) cst).getClassType();
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < sourceCount; i++) {
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                componentType = componentType.getComponentType();
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegisterSpec classReg =
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec.make(dest.getReg(), Type.CLASS);
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (componentType.isPrimitive()) {
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * The component type is primitive (e.g., int as opposed
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * to Integer), so we have to fetch the corresponding
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * TYPE class.
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                CstFieldRef typeField =
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    CstFieldRef.forPrimitiveType(componentType);
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                insn = new ThrowingCstInsn(Rops.GET_STATIC_OBJECT, pos,
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                           RegisterSpecList.EMPTY,
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                           catches, typeField);
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * The component type is an object type, so just make a
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * normal class reference.
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                insn = new ThrowingCstInsn(Rops.CONST_OBJECT, pos,
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                           RegisterSpecList.EMPTY, catches,
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                           new CstType(componentType));
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insns.add(insn);
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // Add a move-result-pseudo for the get-static or const
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            rop = Rops.opMoveResultPseudo(classReg.getType());
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insn = new PlainInsn(rop, pos, classReg, RegisterSpecList.EMPTY);
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insns.add(insn);
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Add a call to the "multianewarray method," that is,
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Array.newInstance(class, dims). Note: The result type
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * of newInstance() is Object, which is why the last
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * instruction in this sequence is a cast to the right
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * type for the original instruction.
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegisterSpec objectReg =
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec.make(dest.getReg(), Type.OBJECT);
442de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insn = new ThrowingCstInsn(
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    Rops.opInvokeStatic(MULTIANEWARRAY_METHOD.getPrototype()),
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pos, RegisterSpecList.make(classReg, dimsReg),
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    catches, MULTIANEWARRAY_METHOD);
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insns.add(insn);
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
449d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein            // Add a move-result.
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            rop = Rops.opMoveResult(MULTIANEWARRAY_METHOD.getPrototype()
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    .getReturnType());
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insn = new PlainInsn(rop, pos, objectReg, RegisterSpecList.EMPTY);
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insns.add(insn);
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * And finally, set up for the remainder of this method to
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * add an appropriate cast.
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            opcode = ByteOps.CHECKCAST;
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sources = RegisterSpecList.make(objectReg);
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (opcode == ByteOps.JSR) {
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // JSR has no Rop instruction
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            hasJsr = true;
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (opcode == ByteOps.RET) {
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            try {
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                returnAddress = (ReturnAddress)arg(0);
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } catch (ClassCastException ex) {
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new RuntimeException(
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        "Argument to RET was not a ReturnAddress", ex);
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // RET has no Rop instruction.
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return;
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ropOpcode = jopToRopOpcode(opcode, cst);
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        rop = Rops.ropFor(ropOpcode, destType, sources, cst);
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Insn moveResult = null;
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (dest != null && rop.isCallLike()) {
482d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein            /*
483d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein             * We're going to want to have a move-result in the next
484d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein             * basic block.
485d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein             */
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            extraBlockCount++;
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            moveResult = new PlainInsn(
489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    Rops.opMoveResult(((CstMethodRef) cst).getPrototype()
490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    .getReturnType()), pos, dest, RegisterSpecList.EMPTY);
491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dest = null;
493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (dest != null && rop.canThrow()) {
494d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein            /*
495d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein             * We're going to want to have a move-result-pseudo in the
496d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein             * next basic block.
497d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein             */
498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            extraBlockCount++;
499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            moveResult = new PlainInsn(
501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    Rops.opMoveResultPseudo(dest.getTypeBearer()),
502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    pos, dest, RegisterSpecList.EMPTY);
503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dest = null;
505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ropOpcode == RegOps.NEW_ARRAY) {
507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * In the original bytecode, this was either a primitive
509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * array constructor "newarray" or an object array
510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * constructor "anewarray". In the former case, there is
511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * no explicit constant, and in the latter, the constant
512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * is for the element type and not the array type. The rop
513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * instruction form for both of these is supposed to be
514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * the resulting array type, so we initialize / alter
515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * "cst" here, accordingly. Conveniently enough, the rop
516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * opcode already gets constructed with the proper array
517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * type.
518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cst = CstType.intern(rop.getResult());
520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if ((cst == null) && (sourceCount == 2)) {
5214596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao            TypeBearer firstType = sources.get(0).getTypeBearer();
522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            TypeBearer lastType = sources.get(1).getTypeBearer();
523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
5244596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao            if ((lastType.isConstant() || firstType.isConstant()) &&
5254596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                 advice.hasConstantOperation(rop, sources.get(0),
5264596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                                             sources.get(1))) {
5274596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao
5284596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                if (lastType.isConstant()) {
5294596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                    /*
5304596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                     * The target architecture has an instruction that can
5314596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                     * build in the constant found in the second argument,
5324596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                     * so pull it out of the sources and just use it as a
5334596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                     * constant here.
5344596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                     */
5354596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                    cst = (Constant) lastType;
5364596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                    sources = sources.withoutLast();
5374596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao
5384596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                    // For subtraction, change to addition and invert constant
5394596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                    if (rop.getOpcode() == RegOps.SUB) {
5404596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                        ropOpcode = RegOps.ADD;
5414596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                        CstInteger cstInt = (CstInteger) lastType;
5424596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                        cst = CstInteger.make(-cstInt.getValue());
5434596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                    }
5444596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                } else {
5454596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                    /*
5464596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                     * The target architecture has an instruction that can
5474596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                     * build in the constant found in the first argument,
5484596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                     * so pull it out of the sources and just use it as a
5494596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                     * constant here.
5504596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                     */
5514596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                    cst = (Constant) firstType;
5524596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                    sources = sources.withoutFirst();
5534596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao                }
5544596322b12a72cdeea8deba1242d9b74da5ba12ajeffhao
555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                rop = Rops.ropFor(ropOpcode, destType, sources, cst);
556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        SwitchList cases = getAuxCases();
560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ArrayList<Constant> initValues = getInitValues();
561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean canThrow = rop.canThrow();
562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        blockCanThrow |= canThrow;
564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (cases != null) {
566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (cases.size() == 0) {
567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // It's a default-only switch statement. It can happen!
568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                insn = new PlainInsn(Rops.GOTO, pos, null,
569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                     RegisterSpecList.EMPTY);
570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                primarySuccessorIndex = 0;
571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                IntList values = cases.getValues();
573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                insn = new SwitchInsn(rop, pos, dest, sources, values);
574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                primarySuccessorIndex = values.size();
575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (ropOpcode == RegOps.RETURN) {
577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /*
578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * Returns get turned into the combination of a move (if
579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * non-void and if the return doesn't already mention
580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             * register 0) and a goto (to the return block).
581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project             */
582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (sources.size() != 0) {
583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec source = sources.get(0);
584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                TypeBearer type = source.getTypeBearer();
585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (source.getReg() != 0) {
586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    insns.add(new PlainInsn(Rops.opMove(type), pos,
587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                            RegisterSpec.make(0, type),
588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                            source));
589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insn = new PlainInsn(Rops.GOTO, pos, null, RegisterSpecList.EMPTY);
592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            primarySuccessorIndex = 0;
593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            updateReturnOp(rop, pos);
594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            returns = true;
595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (cst != null) {
596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (canThrow) {
597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                insn =
598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    new ThrowingCstInsn(rop, pos, sources, catches, cst);
599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                catchesUsed = true;
600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                primarySuccessorIndex = catches.size();
601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                insn = new PlainCstInsn(rop, pos, dest, sources, cst);
603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (canThrow) {
605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insn = new ThrowingInsn(rop, pos, sources, catches);
606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            catchesUsed = true;
607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (opcode == ByteOps.ATHROW) {
608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * The op athrow is the only one where it's possible
610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * to have non-empty successors and yet not have a
611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * primary successor.
612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                primarySuccessorIndex = -1;
614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } else {
615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                primarySuccessorIndex = catches.size();
616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insn = new PlainInsn(rop, pos, dest, sources);
619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        insns.add(insn);
622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (moveResult != null) {
624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insns.add(moveResult);
625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
628d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein         * If initValues is non-null, it means that the parser has
629d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein         * seen a group of compatible constant initialization
630d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein         * bytecodes that are applied to the current newarray. The
631d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein         * action we take here is to convert these initialization
632d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein         * bytecodes into a single fill-array-data ROP which lays out
633d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein         * all the constant values in a table.
634de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro         */
635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (initValues != null) {
636f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            extraBlockCount++;
637f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insn = new FillArrayDataInsn(Rops.FILL_ARRAY_DATA, pos,
638f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    RegisterSpecList.make(moveResult.getResult()), initValues,
639f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    cst);
640f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            insns.add(insn);
641f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
642f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
643f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
644f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
645f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper for {@link #run}, which gets the list of sources for the.
646f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instruction.
647de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
648f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param opcode the opcode being translated
649d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein     * @param stackPointer {@code >= 0;} the stack pointer after the
650d24414a5d1780ce25179f3467b228f9a53863fb4Dan Bornstein     * instruction's arguments have been popped
65199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the sources
652f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
653f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private RegisterSpecList getSources(int opcode, int stackPointer) {
654f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int count = argCount();
655f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
656f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (count == 0) {
657f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // We get an easy out if there aren't any sources.
658f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return RegisterSpecList.EMPTY;
659de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro        }
660f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
661f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int localIndex = getLocalIndex();
662f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        RegisterSpecList sources;
663f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
664f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (localIndex >= 0) {
665f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // The instruction is operating on a local variable.
666f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sources = new RegisterSpecList(1);
667f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sources.set(0, RegisterSpec.make(localIndex, arg(0)));
668f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
669f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sources = new RegisterSpecList(count);
670f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int regAt = stackPointer;
671f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < count; i++) {
672f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                RegisterSpec spec = RegisterSpec.make(regAt, arg(i));
673f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sources.set(i, spec);
674f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                regAt += spec.getCategory();
675f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
676f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
677f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (opcode) {
678f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case ByteOps.IASTORE: {
679f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /*
680f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * The Java argument order for array stores is
681f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * (array, index, value), but the rop argument
682f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * order is (value, array, index). The following
683f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * code gets the right arguments in the right
684f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * places.
685f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
686f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (count != 3) {
687f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        throw new RuntimeException("shouldn't happen");
688f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
689f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    RegisterSpec array = sources.get(0);
690f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    RegisterSpec index = sources.get(1);
691f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    RegisterSpec value = sources.get(2);
692f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    sources.set(0, value);
693f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    sources.set(1, array);
694f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    sources.set(2, index);
695f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
696f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
697f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                case ByteOps.PUTFIELD: {
698f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    /*
699f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * Similar to above: The Java argument order for
700f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * putfield is (object, value), but the rop
701f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     * argument order is (value, object).
702f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                     */
703f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (count != 2) {
704f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        throw new RuntimeException("shouldn't happen");
705f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
706f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    RegisterSpec obj = sources.get(0);
707f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    RegisterSpec value = sources.get(1);
708f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    sources.set(0, value);
709f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    sources.set(1, obj);
710f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    break;
711f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
712f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
713f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
714f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
715f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sources.setImmutable();
716f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sources;
717f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
718f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
719f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
720f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Sets or updates the information about the return block.
721de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
72299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param op {@code non-null;} the opcode to use
72399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param pos {@code non-null;} the position to use
724f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
725f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void updateReturnOp(Rop op, SourcePosition pos) {
726f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (op == null) {
727f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("op == null");
728f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
729f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
730f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (pos == null) {
731f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("pos == null");
732f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
733f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
734f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (returnOp == null) {
735f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            returnOp = op;
736f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            returnPosition = pos;
737f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
738f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (returnOp != op) {
739f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new SimException("return op mismatch: " + op + ", " +
740f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                       returnOp);
741f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
742f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
743f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (pos.getLine() > returnPosition.getLine()) {
744f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // Pick the largest line number to be the "canonical" return.
745f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                returnPosition = pos;
746f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
747f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
748f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
749f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
750f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
751f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the register opcode for the given Java opcode.
752de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
75399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param jop {@code >= 0;} the Java opcode
75499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param cst {@code null-ok;} the constant argument, if any
75599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= 0;} the corresponding register opcode
756f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
757f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int jopToRopOpcode(int jop, Constant cst) {
758f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        switch (jop) {
759f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.POP:
760f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.POP2:
761f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.DUP:
762f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.DUP_X1:
763f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.DUP_X2:
764f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.DUP2:
765f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.DUP2_X1:
766f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.DUP2_X2:
767f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.SWAP:
768f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.JSR:
769f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.RET:
770f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.MULTIANEWARRAY: {
771f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // These need to be taken care of specially.
772f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
773f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
774f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.NOP: {
775f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.NOP;
776f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
777f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.LDC:
778f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.LDC2_W: {
779f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.CONST;
780f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
781de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro            case ByteOps.ILOAD:
782f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.ISTORE: {
783f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.MOVE;
784f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
785f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IALOAD: {
786f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.AGET;
787f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
788f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IASTORE: {
789f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.APUT;
790f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
791f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IADD:
792f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IINC: {
793f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.ADD;
794f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
795f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.ISUB: {
796f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.SUB;
797f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
798f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IMUL: {
799f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.MUL;
800f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
801f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IDIV: {
802f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.DIV;
803f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
804f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IREM: {
805f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.REM;
806f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
807f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.INEG: {
808f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.NEG;
809f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
810f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.ISHL: {
811f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.SHL;
812f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
813f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.ISHR: {
814f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.SHR;
815f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
816f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IUSHR: {
817f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.USHR;
818f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
819f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IAND: {
820f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.AND;
821f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
822f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IOR: {
823f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.OR;
824f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
825f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IXOR: {
826f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.XOR;
827f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
828f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.I2L:
829f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.I2F:
830f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.I2D:
831f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.L2I:
832f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.L2F:
833f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.L2D:
834f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.F2I:
835f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.F2L:
836f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.F2D:
837f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.D2I:
838f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.D2L:
839f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.D2F: {
840f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.CONV;
841f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
842f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.I2B: {
843f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.TO_BYTE;
844f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
845f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.I2C: {
846f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.TO_CHAR;
847f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
848f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.I2S: {
849f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.TO_SHORT;
850f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
851f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.LCMP:
852f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.FCMPL:
853f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.DCMPL: {
854f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.CMPL;
855f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
856f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.FCMPG:
857f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.DCMPG: {
858f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.CMPG;
859f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
860f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IFEQ:
861f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IF_ICMPEQ:
862f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IF_ACMPEQ:
863f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IFNULL: {
864f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.IF_EQ;
865f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
866f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IFNE:
867f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IF_ICMPNE:
868f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IF_ACMPNE:
869f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IFNONNULL: {
870f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.IF_NE;
871f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
872f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IFLT:
873f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IF_ICMPLT: {
874f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.IF_LT;
875f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
876f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IFGE:
877f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IF_ICMPGE: {
878f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.IF_GE;
879f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
880f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IFGT:
881f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IF_ICMPGT: {
882f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.IF_GT;
883f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
884f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IFLE:
885f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IF_ICMPLE: {
886f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.IF_LE;
887f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
888f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.GOTO: {
889f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.GOTO;
890f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
891f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.LOOKUPSWITCH: {
892f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.SWITCH;
893f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
894f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.IRETURN:
895f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.RETURN: {
896f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.RETURN;
897f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
898f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.GETSTATIC: {
899f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.GET_STATIC;
900f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
901f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.PUTSTATIC: {
902f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.PUT_STATIC;
903f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
904f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.GETFIELD: {
905f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.GET_FIELD;
906f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
907f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.PUTFIELD: {
908f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.PUT_FIELD;
909f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
910f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.INVOKEVIRTUAL: {
911f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.INVOKE_VIRTUAL;
912f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
913f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.INVOKESPECIAL: {
914f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                /*
915f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * Determine whether the opcode should be
916f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * INVOKE_DIRECT or INVOKE_SUPER. See vmspec-2 section 6
917f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * on "invokespecial" as well as section 4.8.2 (7th
918f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 * bullet point) for the gory details.
919f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                 */
920f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                CstMethodRef ref = (CstMethodRef) cst;
921f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (ref.isInstanceInit() ||
922f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    (ref.getDefiningClass() == method.getDefiningClass()) ||
923f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    !method.getAccSuper()) {
924f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return RegOps.INVOKE_DIRECT;
925f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
926f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.INVOKE_SUPER;
927f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
928f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.INVOKESTATIC: {
929f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.INVOKE_STATIC;
930f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
931f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.INVOKEINTERFACE: {
932f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.INVOKE_INTERFACE;
933f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
934f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.NEW: {
935f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.NEW_INSTANCE;
936f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
937f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.NEWARRAY:
938f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.ANEWARRAY: {
939f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.NEW_ARRAY;
940f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
941f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.ARRAYLENGTH: {
942f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.ARRAY_LENGTH;
943f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
944f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.ATHROW: {
945f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.THROW;
946f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
947f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.CHECKCAST: {
948f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.CHECK_CAST;
949f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
950f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.INSTANCEOF: {
951f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.INSTANCE_OF;
952f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
953f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.MONITORENTER: {
954f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.MONITOR_ENTER;
955f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
956f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case ByteOps.MONITOREXIT: {
957f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return RegOps.MONITOR_EXIT;
958f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
959f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
960f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
961f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throw new RuntimeException("shouldn't happen");
962f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
963f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
964