1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.dx.dex.code;
18 
19 import com.android.dx.rop.code.Insn;
20 import com.android.dx.rop.code.RegOps;
21 import com.android.dx.rop.code.RegisterSpec;
22 import com.android.dx.rop.code.Rop;
23 import com.android.dx.rop.code.Rops;
24 import com.android.dx.rop.code.ThrowingCstInsn;
25 import com.android.dx.rop.cst.Constant;
26 import com.android.dx.rop.cst.CstFieldRef;
27 import com.android.dx.rop.cst.CstMethodHandle;
28 import com.android.dx.rop.cst.CstProtoRef;
29 import com.android.dx.rop.cst.CstString;
30 import com.android.dx.rop.cst.CstType;
31 import com.android.dx.rop.type.Type;
32 import java.util.HashMap;
33 
34 /**
35  * Translator from rop-level {@link Insn} instances to corresponding
36  * {@link Dop} instances.
37  */
38 public final class RopToDop {
39     /** {@code non-null;} map from all the common rops to dalvik opcodes */
40     private static final HashMap<Rop, Dop> MAP;
41 
42     /**
43      * This class is uninstantiable.
44      */
RopToDop()45     private RopToDop() {
46         // This space intentionally left blank.
47     }
48 
49     /*
50      * The following comment lists each opcode that should be considered
51      * the "head" of an opcode chain, in terms of the process of fitting
52      * an instruction's arguments to an actual opcode. This list is
53      * automatically generated and may be of use in double-checking the
54      * manually-generated static initialization code for this class.
55      *
56      * TODO: Make opcode-gen produce useful code in this case instead
57      * of just a comment.
58      */
59 
60     // BEGIN(first-opcodes); GENERATED AUTOMATICALLY BY opcode-gen
61     //     Opcodes.NOP
62     //     Opcodes.MOVE
63     //     Opcodes.MOVE_WIDE
64     //     Opcodes.MOVE_OBJECT
65     //     Opcodes.MOVE_RESULT
66     //     Opcodes.MOVE_RESULT_WIDE
67     //     Opcodes.MOVE_RESULT_OBJECT
68     //     Opcodes.MOVE_EXCEPTION
69     //     Opcodes.RETURN_VOID
70     //     Opcodes.RETURN
71     //     Opcodes.RETURN_WIDE
72     //     Opcodes.RETURN_OBJECT
73     //     Opcodes.CONST_4
74     //     Opcodes.CONST_WIDE_16
75     //     Opcodes.CONST_STRING
76     //     Opcodes.CONST_CLASS
77     //     Opcodes.MONITOR_ENTER
78     //     Opcodes.MONITOR_EXIT
79     //     Opcodes.CHECK_CAST
80     //     Opcodes.INSTANCE_OF
81     //     Opcodes.ARRAY_LENGTH
82     //     Opcodes.NEW_INSTANCE
83     //     Opcodes.NEW_ARRAY
84     //     Opcodes.FILLED_NEW_ARRAY
85     //     Opcodes.FILL_ARRAY_DATA
86     //     Opcodes.THROW
87     //     Opcodes.GOTO
88     //     Opcodes.PACKED_SWITCH
89     //     Opcodes.SPARSE_SWITCH
90     //     Opcodes.CMPL_FLOAT
91     //     Opcodes.CMPG_FLOAT
92     //     Opcodes.CMPL_DOUBLE
93     //     Opcodes.CMPG_DOUBLE
94     //     Opcodes.CMP_LONG
95     //     Opcodes.IF_EQ
96     //     Opcodes.IF_NE
97     //     Opcodes.IF_LT
98     //     Opcodes.IF_GE
99     //     Opcodes.IF_GT
100     //     Opcodes.IF_LE
101     //     Opcodes.IF_EQZ
102     //     Opcodes.IF_NEZ
103     //     Opcodes.IF_LTZ
104     //     Opcodes.IF_GEZ
105     //     Opcodes.IF_GTZ
106     //     Opcodes.IF_LEZ
107     //     Opcodes.AGET
108     //     Opcodes.AGET_WIDE
109     //     Opcodes.AGET_OBJECT
110     //     Opcodes.AGET_BOOLEAN
111     //     Opcodes.AGET_BYTE
112     //     Opcodes.AGET_CHAR
113     //     Opcodes.AGET_SHORT
114     //     Opcodes.APUT
115     //     Opcodes.APUT_WIDE
116     //     Opcodes.APUT_OBJECT
117     //     Opcodes.APUT_BOOLEAN
118     //     Opcodes.APUT_BYTE
119     //     Opcodes.APUT_CHAR
120     //     Opcodes.APUT_SHORT
121     //     Opcodes.IGET
122     //     Opcodes.IGET_WIDE
123     //     Opcodes.IGET_OBJECT
124     //     Opcodes.IGET_BOOLEAN
125     //     Opcodes.IGET_BYTE
126     //     Opcodes.IGET_CHAR
127     //     Opcodes.IGET_SHORT
128     //     Opcodes.IPUT
129     //     Opcodes.IPUT_WIDE
130     //     Opcodes.IPUT_OBJECT
131     //     Opcodes.IPUT_BOOLEAN
132     //     Opcodes.IPUT_BYTE
133     //     Opcodes.IPUT_CHAR
134     //     Opcodes.IPUT_SHORT
135     //     Opcodes.SGET
136     //     Opcodes.SGET_WIDE
137     //     Opcodes.SGET_OBJECT
138     //     Opcodes.SGET_BOOLEAN
139     //     Opcodes.SGET_BYTE
140     //     Opcodes.SGET_CHAR
141     //     Opcodes.SGET_SHORT
142     //     Opcodes.SPUT
143     //     Opcodes.SPUT_WIDE
144     //     Opcodes.SPUT_OBJECT
145     //     Opcodes.SPUT_BOOLEAN
146     //     Opcodes.SPUT_BYTE
147     //     Opcodes.SPUT_CHAR
148     //     Opcodes.SPUT_SHORT
149     //     Opcodes.INVOKE_VIRTUAL
150     //     Opcodes.INVOKE_SUPER
151     //     Opcodes.INVOKE_DIRECT
152     //     Opcodes.INVOKE_STATIC
153     //     Opcodes.INVOKE_INTERFACE
154     //     Opcodes.NEG_INT
155     //     Opcodes.NOT_INT
156     //     Opcodes.NEG_LONG
157     //     Opcodes.NOT_LONG
158     //     Opcodes.NEG_FLOAT
159     //     Opcodes.NEG_DOUBLE
160     //     Opcodes.INT_TO_LONG
161     //     Opcodes.INT_TO_FLOAT
162     //     Opcodes.INT_TO_DOUBLE
163     //     Opcodes.LONG_TO_INT
164     //     Opcodes.LONG_TO_FLOAT
165     //     Opcodes.LONG_TO_DOUBLE
166     //     Opcodes.FLOAT_TO_INT
167     //     Opcodes.FLOAT_TO_LONG
168     //     Opcodes.FLOAT_TO_DOUBLE
169     //     Opcodes.DOUBLE_TO_INT
170     //     Opcodes.DOUBLE_TO_LONG
171     //     Opcodes.DOUBLE_TO_FLOAT
172     //     Opcodes.INT_TO_BYTE
173     //     Opcodes.INT_TO_CHAR
174     //     Opcodes.INT_TO_SHORT
175     //     Opcodes.ADD_INT_2ADDR
176     //     Opcodes.SUB_INT_2ADDR
177     //     Opcodes.MUL_INT_2ADDR
178     //     Opcodes.DIV_INT_2ADDR
179     //     Opcodes.REM_INT_2ADDR
180     //     Opcodes.AND_INT_2ADDR
181     //     Opcodes.OR_INT_2ADDR
182     //     Opcodes.XOR_INT_2ADDR
183     //     Opcodes.SHL_INT_2ADDR
184     //     Opcodes.SHR_INT_2ADDR
185     //     Opcodes.USHR_INT_2ADDR
186     //     Opcodes.ADD_LONG_2ADDR
187     //     Opcodes.SUB_LONG_2ADDR
188     //     Opcodes.MUL_LONG_2ADDR
189     //     Opcodes.DIV_LONG_2ADDR
190     //     Opcodes.REM_LONG_2ADDR
191     //     Opcodes.AND_LONG_2ADDR
192     //     Opcodes.OR_LONG_2ADDR
193     //     Opcodes.XOR_LONG_2ADDR
194     //     Opcodes.SHL_LONG_2ADDR
195     //     Opcodes.SHR_LONG_2ADDR
196     //     Opcodes.USHR_LONG_2ADDR
197     //     Opcodes.ADD_FLOAT_2ADDR
198     //     Opcodes.SUB_FLOAT_2ADDR
199     //     Opcodes.MUL_FLOAT_2ADDR
200     //     Opcodes.DIV_FLOAT_2ADDR
201     //     Opcodes.REM_FLOAT_2ADDR
202     //     Opcodes.ADD_DOUBLE_2ADDR
203     //     Opcodes.SUB_DOUBLE_2ADDR
204     //     Opcodes.MUL_DOUBLE_2ADDR
205     //     Opcodes.DIV_DOUBLE_2ADDR
206     //     Opcodes.REM_DOUBLE_2ADDR
207     //     Opcodes.ADD_INT_LIT8
208     //     Opcodes.RSUB_INT_LIT8
209     //     Opcodes.MUL_INT_LIT8
210     //     Opcodes.DIV_INT_LIT8
211     //     Opcodes.REM_INT_LIT8
212     //     Opcodes.AND_INT_LIT8
213     //     Opcodes.OR_INT_LIT8
214     //     Opcodes.XOR_INT_LIT8
215     //     Opcodes.SHL_INT_LIT8
216     //     Opcodes.SHR_INT_LIT8
217     //     Opcodes.USHR_INT_LIT8
218     //     Opcodes.INVOKE_POLYMORPHIC
219     //     Opcodes.INVOKE_CUSTOM
220     //     Opcodes.CONST_METHOD_HANDLE
221     //     Opcodes.CONST_METHOD_TYPE
222     // END(first-opcodes)
223 
224     static {
225         /*
226          * Note: The choices made here are to pick the optimistically
227          * smallest Dalvik opcode, and leave it to later processing to
228          * pessimize. See the automatically-generated comment above
229          * for reference.
230          */
231         MAP = new HashMap<Rop, Dop>(400);
MAP.put(Rops.NOP, Dops.NOP)232         MAP.put(Rops.NOP,               Dops.NOP);
MAP.put(Rops.MOVE_INT, Dops.MOVE)233         MAP.put(Rops.MOVE_INT,          Dops.MOVE);
MAP.put(Rops.MOVE_LONG, Dops.MOVE_WIDE)234         MAP.put(Rops.MOVE_LONG,         Dops.MOVE_WIDE);
MAP.put(Rops.MOVE_FLOAT, Dops.MOVE)235         MAP.put(Rops.MOVE_FLOAT,        Dops.MOVE);
MAP.put(Rops.MOVE_DOUBLE, Dops.MOVE_WIDE)236         MAP.put(Rops.MOVE_DOUBLE,       Dops.MOVE_WIDE);
MAP.put(Rops.MOVE_OBJECT, Dops.MOVE_OBJECT)237         MAP.put(Rops.MOVE_OBJECT,       Dops.MOVE_OBJECT);
MAP.put(Rops.MOVE_PARAM_INT, Dops.MOVE)238         MAP.put(Rops.MOVE_PARAM_INT,    Dops.MOVE);
MAP.put(Rops.MOVE_PARAM_LONG, Dops.MOVE_WIDE)239         MAP.put(Rops.MOVE_PARAM_LONG,   Dops.MOVE_WIDE);
MAP.put(Rops.MOVE_PARAM_FLOAT, Dops.MOVE)240         MAP.put(Rops.MOVE_PARAM_FLOAT,  Dops.MOVE);
MAP.put(Rops.MOVE_PARAM_DOUBLE, Dops.MOVE_WIDE)241         MAP.put(Rops.MOVE_PARAM_DOUBLE, Dops.MOVE_WIDE);
MAP.put(Rops.MOVE_PARAM_OBJECT, Dops.MOVE_OBJECT)242         MAP.put(Rops.MOVE_PARAM_OBJECT, Dops.MOVE_OBJECT);
243 
244         /*
245          * Note: No entry for MOVE_EXCEPTION, since it varies by
246          * exception type. (That is, there is no unique instance to
247          * add to the map.)
248          */
249 
MAP.put(Rops.CONST_INT, Dops.CONST_4)250         MAP.put(Rops.CONST_INT,         Dops.CONST_4);
MAP.put(Rops.CONST_LONG, Dops.CONST_WIDE_16)251         MAP.put(Rops.CONST_LONG,        Dops.CONST_WIDE_16);
MAP.put(Rops.CONST_FLOAT, Dops.CONST_4)252         MAP.put(Rops.CONST_FLOAT,       Dops.CONST_4);
MAP.put(Rops.CONST_DOUBLE, Dops.CONST_WIDE_16)253         MAP.put(Rops.CONST_DOUBLE,      Dops.CONST_WIDE_16);
254 
255         /*
256          * Note: No entry for CONST_OBJECT, since it needs to turn
257          * into either CONST_STRING or CONST_CLASS.
258          */
259 
260         /*
261          * TODO: I think the only case of this is for null, and
262          * const/4 should cover that.
263          */
MAP.put(Rops.CONST_OBJECT_NOTHROW, Dops.CONST_4)264         MAP.put(Rops.CONST_OBJECT_NOTHROW, Dops.CONST_4);
265 
MAP.put(Rops.GOTO, Dops.GOTO)266         MAP.put(Rops.GOTO,                 Dops.GOTO);
MAP.put(Rops.IF_EQZ_INT, Dops.IF_EQZ)267         MAP.put(Rops.IF_EQZ_INT,           Dops.IF_EQZ);
MAP.put(Rops.IF_NEZ_INT, Dops.IF_NEZ)268         MAP.put(Rops.IF_NEZ_INT,           Dops.IF_NEZ);
MAP.put(Rops.IF_LTZ_INT, Dops.IF_LTZ)269         MAP.put(Rops.IF_LTZ_INT,           Dops.IF_LTZ);
MAP.put(Rops.IF_GEZ_INT, Dops.IF_GEZ)270         MAP.put(Rops.IF_GEZ_INT,           Dops.IF_GEZ);
MAP.put(Rops.IF_LEZ_INT, Dops.IF_LEZ)271         MAP.put(Rops.IF_LEZ_INT,           Dops.IF_LEZ);
MAP.put(Rops.IF_GTZ_INT, Dops.IF_GTZ)272         MAP.put(Rops.IF_GTZ_INT,           Dops.IF_GTZ);
MAP.put(Rops.IF_EQZ_OBJECT, Dops.IF_EQZ)273         MAP.put(Rops.IF_EQZ_OBJECT,        Dops.IF_EQZ);
MAP.put(Rops.IF_NEZ_OBJECT, Dops.IF_NEZ)274         MAP.put(Rops.IF_NEZ_OBJECT,        Dops.IF_NEZ);
MAP.put(Rops.IF_EQ_INT, Dops.IF_EQ)275         MAP.put(Rops.IF_EQ_INT,            Dops.IF_EQ);
MAP.put(Rops.IF_NE_INT, Dops.IF_NE)276         MAP.put(Rops.IF_NE_INT,            Dops.IF_NE);
MAP.put(Rops.IF_LT_INT, Dops.IF_LT)277         MAP.put(Rops.IF_LT_INT,            Dops.IF_LT);
MAP.put(Rops.IF_GE_INT, Dops.IF_GE)278         MAP.put(Rops.IF_GE_INT,            Dops.IF_GE);
MAP.put(Rops.IF_LE_INT, Dops.IF_LE)279         MAP.put(Rops.IF_LE_INT,            Dops.IF_LE);
MAP.put(Rops.IF_GT_INT, Dops.IF_GT)280         MAP.put(Rops.IF_GT_INT,            Dops.IF_GT);
MAP.put(Rops.IF_EQ_OBJECT, Dops.IF_EQ)281         MAP.put(Rops.IF_EQ_OBJECT,         Dops.IF_EQ);
MAP.put(Rops.IF_NE_OBJECT, Dops.IF_NE)282         MAP.put(Rops.IF_NE_OBJECT,         Dops.IF_NE);
MAP.put(Rops.SWITCH, Dops.SPARSE_SWITCH)283         MAP.put(Rops.SWITCH,               Dops.SPARSE_SWITCH);
MAP.put(Rops.ADD_INT, Dops.ADD_INT_2ADDR)284         MAP.put(Rops.ADD_INT,              Dops.ADD_INT_2ADDR);
MAP.put(Rops.ADD_LONG, Dops.ADD_LONG_2ADDR)285         MAP.put(Rops.ADD_LONG,             Dops.ADD_LONG_2ADDR);
MAP.put(Rops.ADD_FLOAT, Dops.ADD_FLOAT_2ADDR)286         MAP.put(Rops.ADD_FLOAT,            Dops.ADD_FLOAT_2ADDR);
MAP.put(Rops.ADD_DOUBLE, Dops.ADD_DOUBLE_2ADDR)287         MAP.put(Rops.ADD_DOUBLE,           Dops.ADD_DOUBLE_2ADDR);
MAP.put(Rops.SUB_INT, Dops.SUB_INT_2ADDR)288         MAP.put(Rops.SUB_INT,              Dops.SUB_INT_2ADDR);
MAP.put(Rops.SUB_LONG, Dops.SUB_LONG_2ADDR)289         MAP.put(Rops.SUB_LONG,             Dops.SUB_LONG_2ADDR);
MAP.put(Rops.SUB_FLOAT, Dops.SUB_FLOAT_2ADDR)290         MAP.put(Rops.SUB_FLOAT,            Dops.SUB_FLOAT_2ADDR);
MAP.put(Rops.SUB_DOUBLE, Dops.SUB_DOUBLE_2ADDR)291         MAP.put(Rops.SUB_DOUBLE,           Dops.SUB_DOUBLE_2ADDR);
MAP.put(Rops.MUL_INT, Dops.MUL_INT_2ADDR)292         MAP.put(Rops.MUL_INT,              Dops.MUL_INT_2ADDR);
MAP.put(Rops.MUL_LONG, Dops.MUL_LONG_2ADDR)293         MAP.put(Rops.MUL_LONG,             Dops.MUL_LONG_2ADDR);
MAP.put(Rops.MUL_FLOAT, Dops.MUL_FLOAT_2ADDR)294         MAP.put(Rops.MUL_FLOAT,            Dops.MUL_FLOAT_2ADDR);
MAP.put(Rops.MUL_DOUBLE, Dops.MUL_DOUBLE_2ADDR)295         MAP.put(Rops.MUL_DOUBLE,           Dops.MUL_DOUBLE_2ADDR);
MAP.put(Rops.DIV_INT, Dops.DIV_INT_2ADDR)296         MAP.put(Rops.DIV_INT,              Dops.DIV_INT_2ADDR);
MAP.put(Rops.DIV_LONG, Dops.DIV_LONG_2ADDR)297         MAP.put(Rops.DIV_LONG,             Dops.DIV_LONG_2ADDR);
MAP.put(Rops.DIV_FLOAT, Dops.DIV_FLOAT_2ADDR)298         MAP.put(Rops.DIV_FLOAT,            Dops.DIV_FLOAT_2ADDR);
MAP.put(Rops.DIV_DOUBLE, Dops.DIV_DOUBLE_2ADDR)299         MAP.put(Rops.DIV_DOUBLE,           Dops.DIV_DOUBLE_2ADDR);
MAP.put(Rops.REM_INT, Dops.REM_INT_2ADDR)300         MAP.put(Rops.REM_INT,              Dops.REM_INT_2ADDR);
MAP.put(Rops.REM_LONG, Dops.REM_LONG_2ADDR)301         MAP.put(Rops.REM_LONG,             Dops.REM_LONG_2ADDR);
MAP.put(Rops.REM_FLOAT, Dops.REM_FLOAT_2ADDR)302         MAP.put(Rops.REM_FLOAT,            Dops.REM_FLOAT_2ADDR);
MAP.put(Rops.REM_DOUBLE, Dops.REM_DOUBLE_2ADDR)303         MAP.put(Rops.REM_DOUBLE,           Dops.REM_DOUBLE_2ADDR);
MAP.put(Rops.NEG_INT, Dops.NEG_INT)304         MAP.put(Rops.NEG_INT,              Dops.NEG_INT);
MAP.put(Rops.NEG_LONG, Dops.NEG_LONG)305         MAP.put(Rops.NEG_LONG,             Dops.NEG_LONG);
MAP.put(Rops.NEG_FLOAT, Dops.NEG_FLOAT)306         MAP.put(Rops.NEG_FLOAT,            Dops.NEG_FLOAT);
MAP.put(Rops.NEG_DOUBLE, Dops.NEG_DOUBLE)307         MAP.put(Rops.NEG_DOUBLE,           Dops.NEG_DOUBLE);
MAP.put(Rops.AND_INT, Dops.AND_INT_2ADDR)308         MAP.put(Rops.AND_INT,              Dops.AND_INT_2ADDR);
MAP.put(Rops.AND_LONG, Dops.AND_LONG_2ADDR)309         MAP.put(Rops.AND_LONG,             Dops.AND_LONG_2ADDR);
MAP.put(Rops.OR_INT, Dops.OR_INT_2ADDR)310         MAP.put(Rops.OR_INT,               Dops.OR_INT_2ADDR);
MAP.put(Rops.OR_LONG, Dops.OR_LONG_2ADDR)311         MAP.put(Rops.OR_LONG,              Dops.OR_LONG_2ADDR);
MAP.put(Rops.XOR_INT, Dops.XOR_INT_2ADDR)312         MAP.put(Rops.XOR_INT,              Dops.XOR_INT_2ADDR);
MAP.put(Rops.XOR_LONG, Dops.XOR_LONG_2ADDR)313         MAP.put(Rops.XOR_LONG,             Dops.XOR_LONG_2ADDR);
MAP.put(Rops.SHL_INT, Dops.SHL_INT_2ADDR)314         MAP.put(Rops.SHL_INT,              Dops.SHL_INT_2ADDR);
MAP.put(Rops.SHL_LONG, Dops.SHL_LONG_2ADDR)315         MAP.put(Rops.SHL_LONG,             Dops.SHL_LONG_2ADDR);
MAP.put(Rops.SHR_INT, Dops.SHR_INT_2ADDR)316         MAP.put(Rops.SHR_INT,              Dops.SHR_INT_2ADDR);
MAP.put(Rops.SHR_LONG, Dops.SHR_LONG_2ADDR)317         MAP.put(Rops.SHR_LONG,             Dops.SHR_LONG_2ADDR);
MAP.put(Rops.USHR_INT, Dops.USHR_INT_2ADDR)318         MAP.put(Rops.USHR_INT,             Dops.USHR_INT_2ADDR);
MAP.put(Rops.USHR_LONG, Dops.USHR_LONG_2ADDR)319         MAP.put(Rops.USHR_LONG,            Dops.USHR_LONG_2ADDR);
MAP.put(Rops.NOT_INT, Dops.NOT_INT)320         MAP.put(Rops.NOT_INT,              Dops.NOT_INT);
MAP.put(Rops.NOT_LONG, Dops.NOT_LONG)321         MAP.put(Rops.NOT_LONG,             Dops.NOT_LONG);
322 
MAP.put(Rops.ADD_CONST_INT, Dops.ADD_INT_LIT8)323         MAP.put(Rops.ADD_CONST_INT,        Dops.ADD_INT_LIT8);
324         // Note: No dalvik ops for other types of add_const.
325 
MAP.put(Rops.SUB_CONST_INT, Dops.RSUB_INT_LIT8)326         MAP.put(Rops.SUB_CONST_INT,        Dops.RSUB_INT_LIT8);
327         /*
328          * Note: No dalvik ops for any type of sub_const; instead
329          * there's a *reverse* sub (constant - reg) for ints only.
330          */
331 
MAP.put(Rops.MUL_CONST_INT, Dops.MUL_INT_LIT8)332         MAP.put(Rops.MUL_CONST_INT,        Dops.MUL_INT_LIT8);
333         // Note: No dalvik ops for other types of mul_const.
334 
MAP.put(Rops.DIV_CONST_INT, Dops.DIV_INT_LIT8)335         MAP.put(Rops.DIV_CONST_INT,        Dops.DIV_INT_LIT8);
336         // Note: No dalvik ops for other types of div_const.
337 
MAP.put(Rops.REM_CONST_INT, Dops.REM_INT_LIT8)338         MAP.put(Rops.REM_CONST_INT,        Dops.REM_INT_LIT8);
339         // Note: No dalvik ops for other types of rem_const.
340 
MAP.put(Rops.AND_CONST_INT, Dops.AND_INT_LIT8)341         MAP.put(Rops.AND_CONST_INT,        Dops.AND_INT_LIT8);
342         // Note: No dalvik op for and_const_long.
343 
MAP.put(Rops.OR_CONST_INT, Dops.OR_INT_LIT8)344         MAP.put(Rops.OR_CONST_INT,         Dops.OR_INT_LIT8);
345         // Note: No dalvik op for or_const_long.
346 
MAP.put(Rops.XOR_CONST_INT, Dops.XOR_INT_LIT8)347         MAP.put(Rops.XOR_CONST_INT,        Dops.XOR_INT_LIT8);
348         // Note: No dalvik op for xor_const_long.
349 
MAP.put(Rops.SHL_CONST_INT, Dops.SHL_INT_LIT8)350         MAP.put(Rops.SHL_CONST_INT,        Dops.SHL_INT_LIT8);
351         // Note: No dalvik op for shl_const_long.
352 
MAP.put(Rops.SHR_CONST_INT, Dops.SHR_INT_LIT8)353         MAP.put(Rops.SHR_CONST_INT,        Dops.SHR_INT_LIT8);
354         // Note: No dalvik op for shr_const_long.
355 
MAP.put(Rops.USHR_CONST_INT, Dops.USHR_INT_LIT8)356         MAP.put(Rops.USHR_CONST_INT,       Dops.USHR_INT_LIT8);
357         // Note: No dalvik op for shr_const_long.
358 
MAP.put(Rops.CMPL_LONG, Dops.CMP_LONG)359         MAP.put(Rops.CMPL_LONG,            Dops.CMP_LONG);
MAP.put(Rops.CMPL_FLOAT, Dops.CMPL_FLOAT)360         MAP.put(Rops.CMPL_FLOAT,           Dops.CMPL_FLOAT);
MAP.put(Rops.CMPL_DOUBLE, Dops.CMPL_DOUBLE)361         MAP.put(Rops.CMPL_DOUBLE,          Dops.CMPL_DOUBLE);
MAP.put(Rops.CMPG_FLOAT, Dops.CMPG_FLOAT)362         MAP.put(Rops.CMPG_FLOAT,           Dops.CMPG_FLOAT);
MAP.put(Rops.CMPG_DOUBLE, Dops.CMPG_DOUBLE)363         MAP.put(Rops.CMPG_DOUBLE,          Dops.CMPG_DOUBLE);
MAP.put(Rops.CONV_L2I, Dops.LONG_TO_INT)364         MAP.put(Rops.CONV_L2I,             Dops.LONG_TO_INT);
MAP.put(Rops.CONV_F2I, Dops.FLOAT_TO_INT)365         MAP.put(Rops.CONV_F2I,             Dops.FLOAT_TO_INT);
MAP.put(Rops.CONV_D2I, Dops.DOUBLE_TO_INT)366         MAP.put(Rops.CONV_D2I,             Dops.DOUBLE_TO_INT);
MAP.put(Rops.CONV_I2L, Dops.INT_TO_LONG)367         MAP.put(Rops.CONV_I2L,             Dops.INT_TO_LONG);
MAP.put(Rops.CONV_F2L, Dops.FLOAT_TO_LONG)368         MAP.put(Rops.CONV_F2L,             Dops.FLOAT_TO_LONG);
MAP.put(Rops.CONV_D2L, Dops.DOUBLE_TO_LONG)369         MAP.put(Rops.CONV_D2L,             Dops.DOUBLE_TO_LONG);
MAP.put(Rops.CONV_I2F, Dops.INT_TO_FLOAT)370         MAP.put(Rops.CONV_I2F,             Dops.INT_TO_FLOAT);
MAP.put(Rops.CONV_L2F, Dops.LONG_TO_FLOAT)371         MAP.put(Rops.CONV_L2F,             Dops.LONG_TO_FLOAT);
MAP.put(Rops.CONV_D2F, Dops.DOUBLE_TO_FLOAT)372         MAP.put(Rops.CONV_D2F,             Dops.DOUBLE_TO_FLOAT);
MAP.put(Rops.CONV_I2D, Dops.INT_TO_DOUBLE)373         MAP.put(Rops.CONV_I2D,             Dops.INT_TO_DOUBLE);
MAP.put(Rops.CONV_L2D, Dops.LONG_TO_DOUBLE)374         MAP.put(Rops.CONV_L2D,             Dops.LONG_TO_DOUBLE);
MAP.put(Rops.CONV_F2D, Dops.FLOAT_TO_DOUBLE)375         MAP.put(Rops.CONV_F2D,             Dops.FLOAT_TO_DOUBLE);
MAP.put(Rops.TO_BYTE, Dops.INT_TO_BYTE)376         MAP.put(Rops.TO_BYTE,              Dops.INT_TO_BYTE);
MAP.put(Rops.TO_CHAR, Dops.INT_TO_CHAR)377         MAP.put(Rops.TO_CHAR,              Dops.INT_TO_CHAR);
MAP.put(Rops.TO_SHORT, Dops.INT_TO_SHORT)378         MAP.put(Rops.TO_SHORT,             Dops.INT_TO_SHORT);
MAP.put(Rops.RETURN_VOID, Dops.RETURN_VOID)379         MAP.put(Rops.RETURN_VOID,          Dops.RETURN_VOID);
MAP.put(Rops.RETURN_INT, Dops.RETURN)380         MAP.put(Rops.RETURN_INT,           Dops.RETURN);
MAP.put(Rops.RETURN_LONG, Dops.RETURN_WIDE)381         MAP.put(Rops.RETURN_LONG,          Dops.RETURN_WIDE);
MAP.put(Rops.RETURN_FLOAT, Dops.RETURN)382         MAP.put(Rops.RETURN_FLOAT,         Dops.RETURN);
MAP.put(Rops.RETURN_DOUBLE, Dops.RETURN_WIDE)383         MAP.put(Rops.RETURN_DOUBLE,        Dops.RETURN_WIDE);
MAP.put(Rops.RETURN_OBJECT, Dops.RETURN_OBJECT)384         MAP.put(Rops.RETURN_OBJECT,        Dops.RETURN_OBJECT);
MAP.put(Rops.ARRAY_LENGTH, Dops.ARRAY_LENGTH)385         MAP.put(Rops.ARRAY_LENGTH,         Dops.ARRAY_LENGTH);
MAP.put(Rops.THROW, Dops.THROW)386         MAP.put(Rops.THROW,                Dops.THROW);
MAP.put(Rops.MONITOR_ENTER, Dops.MONITOR_ENTER)387         MAP.put(Rops.MONITOR_ENTER,        Dops.MONITOR_ENTER);
MAP.put(Rops.MONITOR_EXIT, Dops.MONITOR_EXIT)388         MAP.put(Rops.MONITOR_EXIT,         Dops.MONITOR_EXIT);
MAP.put(Rops.AGET_INT, Dops.AGET)389         MAP.put(Rops.AGET_INT,             Dops.AGET);
MAP.put(Rops.AGET_LONG, Dops.AGET_WIDE)390         MAP.put(Rops.AGET_LONG,            Dops.AGET_WIDE);
MAP.put(Rops.AGET_FLOAT, Dops.AGET)391         MAP.put(Rops.AGET_FLOAT,           Dops.AGET);
MAP.put(Rops.AGET_DOUBLE, Dops.AGET_WIDE)392         MAP.put(Rops.AGET_DOUBLE,          Dops.AGET_WIDE);
MAP.put(Rops.AGET_OBJECT, Dops.AGET_OBJECT)393         MAP.put(Rops.AGET_OBJECT,          Dops.AGET_OBJECT);
MAP.put(Rops.AGET_BOOLEAN, Dops.AGET_BOOLEAN)394         MAP.put(Rops.AGET_BOOLEAN,         Dops.AGET_BOOLEAN);
MAP.put(Rops.AGET_BYTE, Dops.AGET_BYTE)395         MAP.put(Rops.AGET_BYTE,            Dops.AGET_BYTE);
MAP.put(Rops.AGET_CHAR, Dops.AGET_CHAR)396         MAP.put(Rops.AGET_CHAR,            Dops.AGET_CHAR);
MAP.put(Rops.AGET_SHORT, Dops.AGET_SHORT)397         MAP.put(Rops.AGET_SHORT,           Dops.AGET_SHORT);
MAP.put(Rops.APUT_INT, Dops.APUT)398         MAP.put(Rops.APUT_INT,             Dops.APUT);
MAP.put(Rops.APUT_LONG, Dops.APUT_WIDE)399         MAP.put(Rops.APUT_LONG,            Dops.APUT_WIDE);
MAP.put(Rops.APUT_FLOAT, Dops.APUT)400         MAP.put(Rops.APUT_FLOAT,           Dops.APUT);
MAP.put(Rops.APUT_DOUBLE, Dops.APUT_WIDE)401         MAP.put(Rops.APUT_DOUBLE,          Dops.APUT_WIDE);
MAP.put(Rops.APUT_OBJECT, Dops.APUT_OBJECT)402         MAP.put(Rops.APUT_OBJECT,          Dops.APUT_OBJECT);
MAP.put(Rops.APUT_BOOLEAN, Dops.APUT_BOOLEAN)403         MAP.put(Rops.APUT_BOOLEAN,         Dops.APUT_BOOLEAN);
MAP.put(Rops.APUT_BYTE, Dops.APUT_BYTE)404         MAP.put(Rops.APUT_BYTE,            Dops.APUT_BYTE);
MAP.put(Rops.APUT_CHAR, Dops.APUT_CHAR)405         MAP.put(Rops.APUT_CHAR,            Dops.APUT_CHAR);
MAP.put(Rops.APUT_SHORT, Dops.APUT_SHORT)406         MAP.put(Rops.APUT_SHORT,           Dops.APUT_SHORT);
MAP.put(Rops.NEW_INSTANCE, Dops.NEW_INSTANCE)407         MAP.put(Rops.NEW_INSTANCE,         Dops.NEW_INSTANCE);
MAP.put(Rops.CHECK_CAST, Dops.CHECK_CAST)408         MAP.put(Rops.CHECK_CAST,           Dops.CHECK_CAST);
MAP.put(Rops.INSTANCE_OF, Dops.INSTANCE_OF)409         MAP.put(Rops.INSTANCE_OF,          Dops.INSTANCE_OF);
410 
MAP.put(Rops.GET_FIELD_LONG, Dops.IGET_WIDE)411         MAP.put(Rops.GET_FIELD_LONG,       Dops.IGET_WIDE);
MAP.put(Rops.GET_FIELD_FLOAT, Dops.IGET)412         MAP.put(Rops.GET_FIELD_FLOAT,      Dops.IGET);
MAP.put(Rops.GET_FIELD_DOUBLE, Dops.IGET_WIDE)413         MAP.put(Rops.GET_FIELD_DOUBLE,     Dops.IGET_WIDE);
MAP.put(Rops.GET_FIELD_OBJECT, Dops.IGET_OBJECT)414         MAP.put(Rops.GET_FIELD_OBJECT,     Dops.IGET_OBJECT);
415         /*
416          * Note: No map entries for get_field_* for non-long integral types,
417          * since they need to be handled specially (see dopFor() below).
418          */
419 
MAP.put(Rops.GET_STATIC_LONG, Dops.SGET_WIDE)420         MAP.put(Rops.GET_STATIC_LONG,      Dops.SGET_WIDE);
MAP.put(Rops.GET_STATIC_FLOAT, Dops.SGET)421         MAP.put(Rops.GET_STATIC_FLOAT,     Dops.SGET);
MAP.put(Rops.GET_STATIC_DOUBLE, Dops.SGET_WIDE)422         MAP.put(Rops.GET_STATIC_DOUBLE,    Dops.SGET_WIDE);
MAP.put(Rops.GET_STATIC_OBJECT, Dops.SGET_OBJECT)423         MAP.put(Rops.GET_STATIC_OBJECT,    Dops.SGET_OBJECT);
424         /*
425          * Note: No map entries for get_static* for non-long integral types,
426          * since they need to be handled specially (see dopFor() below).
427          */
428 
MAP.put(Rops.PUT_FIELD_LONG, Dops.IPUT_WIDE)429         MAP.put(Rops.PUT_FIELD_LONG,       Dops.IPUT_WIDE);
MAP.put(Rops.PUT_FIELD_FLOAT, Dops.IPUT)430         MAP.put(Rops.PUT_FIELD_FLOAT,      Dops.IPUT);
MAP.put(Rops.PUT_FIELD_DOUBLE, Dops.IPUT_WIDE)431         MAP.put(Rops.PUT_FIELD_DOUBLE,     Dops.IPUT_WIDE);
MAP.put(Rops.PUT_FIELD_OBJECT, Dops.IPUT_OBJECT)432         MAP.put(Rops.PUT_FIELD_OBJECT,     Dops.IPUT_OBJECT);
433         /*
434          * Note: No map entries for put_field_* for non-long integral types,
435          * since they need to be handled specially (see dopFor() below).
436          */
437 
MAP.put(Rops.PUT_STATIC_LONG, Dops.SPUT_WIDE)438         MAP.put(Rops.PUT_STATIC_LONG,      Dops.SPUT_WIDE);
MAP.put(Rops.PUT_STATIC_FLOAT, Dops.SPUT)439         MAP.put(Rops.PUT_STATIC_FLOAT,     Dops.SPUT);
MAP.put(Rops.PUT_STATIC_DOUBLE, Dops.SPUT_WIDE)440         MAP.put(Rops.PUT_STATIC_DOUBLE,    Dops.SPUT_WIDE);
MAP.put(Rops.PUT_STATIC_OBJECT, Dops.SPUT_OBJECT)441         MAP.put(Rops.PUT_STATIC_OBJECT,    Dops.SPUT_OBJECT);
442         /*
443          * Note: No map entries for put_static* for non-long integral types,
444          * since they need to be handled specially (see dopFor() below).
445          */
446 
447         /*
448          * Note: No map entries for invoke*, new_array, and
449          * filled_new_array, since they need to be handled specially
450          * (see dopFor() below).
451          */
452     }
453 
454     /**
455      * Returns the dalvik opcode appropriate for the given register-based
456      * instruction.
457      *
458      * @param insn {@code non-null;} the original instruction
459      * @return the corresponding dalvik opcode; one of the constants in
460      * {@link Dops}
461      */
dopFor(Insn insn)462     public static Dop dopFor(Insn insn) {
463         Rop rop = insn.getOpcode();
464 
465         /*
466          * First, just try looking up the rop in the MAP of easy
467          * cases.
468          */
469         Dop result = MAP.get(rop);
470         if (result != null) {
471             return result;
472         }
473 
474         /*
475          * There was no easy case for the rop, so look up the opcode, and
476          * do something special for each:
477          *
478          * The move_exception, new_array, filled_new_array, and
479          * invoke* opcodes won't be found in MAP, since they'll each
480          * have different source and/or result register types / lists.
481          *
482          * The get* and put* opcodes for (non-long) integral types
483          * aren't in the map, since the type signatures aren't
484          * sufficient to distinguish between the types (the salient
485          * source or result will always be just "int").
486          *
487          * And const instruction need to distinguish between strings and
488          * classes.
489          */
490 
491         switch (rop.getOpcode()) {
492             case RegOps.MOVE_EXCEPTION:     return Dops.MOVE_EXCEPTION;
493             case RegOps.INVOKE_STATIC:      return Dops.INVOKE_STATIC;
494             case RegOps.INVOKE_VIRTUAL:     return Dops.INVOKE_VIRTUAL;
495             case RegOps.INVOKE_SUPER:       return Dops.INVOKE_SUPER;
496             case RegOps.INVOKE_DIRECT:      return Dops.INVOKE_DIRECT;
497             case RegOps.INVOKE_INTERFACE:   return Dops.INVOKE_INTERFACE;
498             case RegOps.INVOKE_POLYMORPHIC: return Dops.INVOKE_POLYMORPHIC;
499             case RegOps.INVOKE_CUSTOM:      return Dops.INVOKE_CUSTOM;
500             case RegOps.NEW_ARRAY:          return Dops.NEW_ARRAY;
501             case RegOps.FILLED_NEW_ARRAY:   return Dops.FILLED_NEW_ARRAY;
502             case RegOps.FILL_ARRAY_DATA:    return Dops.FILL_ARRAY_DATA;
503             case RegOps.MOVE_RESULT: {
504                 RegisterSpec resultReg = insn.getResult();
505 
506                 if (resultReg == null) {
507                     return Dops.NOP;
508                 } else {
509                     switch (resultReg.getBasicType()) {
510                         case Type.BT_INT:
511                         case Type.BT_FLOAT:
512                         case Type.BT_BOOLEAN:
513                         case Type.BT_BYTE:
514                         case Type.BT_CHAR:
515                         case Type.BT_SHORT:
516                             return Dops.MOVE_RESULT;
517                         case Type.BT_LONG:
518                         case Type.BT_DOUBLE:
519                             return Dops.MOVE_RESULT_WIDE;
520                         case Type.BT_OBJECT:
521                             return Dops.MOVE_RESULT_OBJECT;
522                         default: {
523                             throw new RuntimeException("Unexpected basic type");
524                         }
525                     }
526                 }
527             }
528 
529             case RegOps.GET_FIELD: {
530                 CstFieldRef ref =
531                     (CstFieldRef) ((ThrowingCstInsn) insn).getConstant();
532                 int basicType = ref.getBasicType();
533                 switch (basicType) {
534                     case Type.BT_BOOLEAN: return Dops.IGET_BOOLEAN;
535                     case Type.BT_BYTE:    return Dops.IGET_BYTE;
536                     case Type.BT_CHAR:    return Dops.IGET_CHAR;
537                     case Type.BT_SHORT:   return Dops.IGET_SHORT;
538                     case Type.BT_INT:     return Dops.IGET;
539                 }
540                 break;
541             }
542             case RegOps.PUT_FIELD: {
543                 CstFieldRef ref =
544                     (CstFieldRef) ((ThrowingCstInsn) insn).getConstant();
545                 int basicType = ref.getBasicType();
546                 switch (basicType) {
547                     case Type.BT_BOOLEAN: return Dops.IPUT_BOOLEAN;
548                     case Type.BT_BYTE:    return Dops.IPUT_BYTE;
549                     case Type.BT_CHAR:    return Dops.IPUT_CHAR;
550                     case Type.BT_SHORT:   return Dops.IPUT_SHORT;
551                     case Type.BT_INT:     return Dops.IPUT;
552                 }
553                 break;
554             }
555             case RegOps.GET_STATIC: {
556                 CstFieldRef ref =
557                     (CstFieldRef) ((ThrowingCstInsn) insn).getConstant();
558                 int basicType = ref.getBasicType();
559                 switch (basicType) {
560                     case Type.BT_BOOLEAN: return Dops.SGET_BOOLEAN;
561                     case Type.BT_BYTE:    return Dops.SGET_BYTE;
562                     case Type.BT_CHAR:    return Dops.SGET_CHAR;
563                     case Type.BT_SHORT:   return Dops.SGET_SHORT;
564                     case Type.BT_INT:     return Dops.SGET;
565                 }
566                 break;
567             }
568             case RegOps.PUT_STATIC: {
569                 CstFieldRef ref =
570                     (CstFieldRef) ((ThrowingCstInsn) insn).getConstant();
571                 int basicType = ref.getBasicType();
572                 switch (basicType) {
573                     case Type.BT_BOOLEAN: return Dops.SPUT_BOOLEAN;
574                     case Type.BT_BYTE:    return Dops.SPUT_BYTE;
575                     case Type.BT_CHAR:    return Dops.SPUT_CHAR;
576                     case Type.BT_SHORT:   return Dops.SPUT_SHORT;
577                     case Type.BT_INT:     return Dops.SPUT;
578                 }
579                 break;
580             }
581             case RegOps.CONST: {
582                 Constant cst = ((ThrowingCstInsn) insn).getConstant();
583                 if (cst instanceof CstType) {
584                     return Dops.CONST_CLASS;
585                 } else if (cst instanceof CstString) {
586                     return Dops.CONST_STRING;
587                 } else if (cst instanceof CstMethodHandle) {
588                     return Dops.CONST_METHOD_HANDLE;
589                 } else if (cst instanceof CstProtoRef) {
590                     return Dops.CONST_METHOD_TYPE;
591                 } else {
592                     throw new RuntimeException("Unexpected constant type");
593                 }
594             }
595         }
596 
597         throw new RuntimeException("unknown rop: " + rop);
598     }
599 }
600