Home | History | Annotate | Download | only in code
      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      */
     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);
    232         MAP.put(Rops.NOP,               Dops.NOP);
    233         MAP.put(Rops.MOVE_INT,          Dops.MOVE);
    234         MAP.put(Rops.MOVE_LONG,         Dops.MOVE_WIDE);
    235         MAP.put(Rops.MOVE_FLOAT,        Dops.MOVE);
    236         MAP.put(Rops.MOVE_DOUBLE,       Dops.MOVE_WIDE);
    237         MAP.put(Rops.MOVE_OBJECT,       Dops.MOVE_OBJECT);
    238         MAP.put(Rops.MOVE_PARAM_INT,    Dops.MOVE);
    239         MAP.put(Rops.MOVE_PARAM_LONG,   Dops.MOVE_WIDE);
    240         MAP.put(Rops.MOVE_PARAM_FLOAT,  Dops.MOVE);
    241         MAP.put(Rops.MOVE_PARAM_DOUBLE, Dops.MOVE_WIDE);
    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 
    250         MAP.put(Rops.CONST_INT,         Dops.CONST_4);
    251         MAP.put(Rops.CONST_LONG,        Dops.CONST_WIDE_16);
    252         MAP.put(Rops.CONST_FLOAT,       Dops.CONST_4);
    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          */
    264         MAP.put(Rops.CONST_OBJECT_NOTHROW, Dops.CONST_4);
    265 
    266         MAP.put(Rops.GOTO,                 Dops.GOTO);
    267         MAP.put(Rops.IF_EQZ_INT,           Dops.IF_EQZ);
    268         MAP.put(Rops.IF_NEZ_INT,           Dops.IF_NEZ);
    269         MAP.put(Rops.IF_LTZ_INT,           Dops.IF_LTZ);
    270         MAP.put(Rops.IF_GEZ_INT,           Dops.IF_GEZ);
    271         MAP.put(Rops.IF_LEZ_INT,           Dops.IF_LEZ);
    272         MAP.put(Rops.IF_GTZ_INT,           Dops.IF_GTZ);
    273         MAP.put(Rops.IF_EQZ_OBJECT,        Dops.IF_EQZ);
    274         MAP.put(Rops.IF_NEZ_OBJECT,        Dops.IF_NEZ);
    275         MAP.put(Rops.IF_EQ_INT,            Dops.IF_EQ);
    276         MAP.put(Rops.IF_NE_INT,            Dops.IF_NE);
    277         MAP.put(Rops.IF_LT_INT,            Dops.IF_LT);
    278         MAP.put(Rops.IF_GE_INT,            Dops.IF_GE);
    279         MAP.put(Rops.IF_LE_INT,            Dops.IF_LE);
    280         MAP.put(Rops.IF_GT_INT,            Dops.IF_GT);
    281         MAP.put(Rops.IF_EQ_OBJECT,         Dops.IF_EQ);
    282         MAP.put(Rops.IF_NE_OBJECT,         Dops.IF_NE);
    283         MAP.put(Rops.SWITCH,               Dops.SPARSE_SWITCH);
    284         MAP.put(Rops.ADD_INT,              Dops.ADD_INT_2ADDR);
    285         MAP.put(Rops.ADD_LONG,             Dops.ADD_LONG_2ADDR);
    286         MAP.put(Rops.ADD_FLOAT,            Dops.ADD_FLOAT_2ADDR);
    287         MAP.put(Rops.ADD_DOUBLE,           Dops.ADD_DOUBLE_2ADDR);
    288         MAP.put(Rops.SUB_INT,              Dops.SUB_INT_2ADDR);
    289         MAP.put(Rops.SUB_LONG,             Dops.SUB_LONG_2ADDR);
    290         MAP.put(Rops.SUB_FLOAT,            Dops.SUB_FLOAT_2ADDR);
    291         MAP.put(Rops.SUB_DOUBLE,           Dops.SUB_DOUBLE_2ADDR);
    292         MAP.put(Rops.MUL_INT,              Dops.MUL_INT_2ADDR);
    293         MAP.put(Rops.MUL_LONG,             Dops.MUL_LONG_2ADDR);
    294         MAP.put(Rops.MUL_FLOAT,            Dops.MUL_FLOAT_2ADDR);
    295         MAP.put(Rops.MUL_DOUBLE,           Dops.MUL_DOUBLE_2ADDR);
    296         MAP.put(Rops.DIV_INT,              Dops.DIV_INT_2ADDR);
    297         MAP.put(Rops.DIV_LONG,             Dops.DIV_LONG_2ADDR);
    298         MAP.put(Rops.DIV_FLOAT,            Dops.DIV_FLOAT_2ADDR);
    299         MAP.put(Rops.DIV_DOUBLE,           Dops.DIV_DOUBLE_2ADDR);
    300         MAP.put(Rops.REM_INT,              Dops.REM_INT_2ADDR);
    301         MAP.put(Rops.REM_LONG,             Dops.REM_LONG_2ADDR);
    302         MAP.put(Rops.REM_FLOAT,            Dops.REM_FLOAT_2ADDR);
    303         MAP.put(Rops.REM_DOUBLE,           Dops.REM_DOUBLE_2ADDR);
    304         MAP.put(Rops.NEG_INT,              Dops.NEG_INT);
    305         MAP.put(Rops.NEG_LONG,             Dops.NEG_LONG);
    306         MAP.put(Rops.NEG_FLOAT,            Dops.NEG_FLOAT);
    307         MAP.put(Rops.NEG_DOUBLE,           Dops.NEG_DOUBLE);
    308         MAP.put(Rops.AND_INT,              Dops.AND_INT_2ADDR);
    309         MAP.put(Rops.AND_LONG,             Dops.AND_LONG_2ADDR);
    310         MAP.put(Rops.OR_INT,               Dops.OR_INT_2ADDR);
    311         MAP.put(Rops.OR_LONG,              Dops.OR_LONG_2ADDR);
    312         MAP.put(Rops.XOR_INT,              Dops.XOR_INT_2ADDR);
    313         MAP.put(Rops.XOR_LONG,             Dops.XOR_LONG_2ADDR);
    314         MAP.put(Rops.SHL_INT,              Dops.SHL_INT_2ADDR);
    315         MAP.put(Rops.SHL_LONG,             Dops.SHL_LONG_2ADDR);
    316         MAP.put(Rops.SHR_INT,              Dops.SHR_INT_2ADDR);
    317         MAP.put(Rops.SHR_LONG,             Dops.SHR_LONG_2ADDR);
    318         MAP.put(Rops.USHR_INT,             Dops.USHR_INT_2ADDR);
    319         MAP.put(Rops.USHR_LONG,            Dops.USHR_LONG_2ADDR);
    320         MAP.put(Rops.NOT_INT,              Dops.NOT_INT);
    321         MAP.put(Rops.NOT_LONG,             Dops.NOT_LONG);
    322 
    323         MAP.put(Rops.ADD_CONST_INT,        Dops.ADD_INT_LIT8);
    324         // Note: No dalvik ops for other types of add_const.
    325 
    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 
    332         MAP.put(Rops.MUL_CONST_INT,        Dops.MUL_INT_LIT8);
    333         // Note: No dalvik ops for other types of mul_const.
    334 
    335         MAP.put(Rops.DIV_CONST_INT,        Dops.DIV_INT_LIT8);
    336         // Note: No dalvik ops for other types of div_const.
    337 
    338         MAP.put(Rops.REM_CONST_INT,        Dops.REM_INT_LIT8);
    339         // Note: No dalvik ops for other types of rem_const.
    340 
    341         MAP.put(Rops.AND_CONST_INT,        Dops.AND_INT_LIT8);
    342         // Note: No dalvik op for and_const_long.
    343 
    344         MAP.put(Rops.OR_CONST_INT,         Dops.OR_INT_LIT8);
    345         // Note: No dalvik op for or_const_long.
    346 
    347         MAP.put(Rops.XOR_CONST_INT,        Dops.XOR_INT_LIT8);
    348         // Note: No dalvik op for xor_const_long.
    349 
    350         MAP.put(Rops.SHL_CONST_INT,        Dops.SHL_INT_LIT8);
    351         // Note: No dalvik op for shl_const_long.
    352 
    353         MAP.put(Rops.SHR_CONST_INT,        Dops.SHR_INT_LIT8);
    354         // Note: No dalvik op for shr_const_long.
    355 
    356         MAP.put(Rops.USHR_CONST_INT,       Dops.USHR_INT_LIT8);
    357         // Note: No dalvik op for shr_const_long.
    358 
    359         MAP.put(Rops.CMPL_LONG,            Dops.CMP_LONG);
    360         MAP.put(Rops.CMPL_FLOAT,           Dops.CMPL_FLOAT);
    361         MAP.put(Rops.CMPL_DOUBLE,          Dops.CMPL_DOUBLE);
    362         MAP.put(Rops.CMPG_FLOAT,           Dops.CMPG_FLOAT);
    363         MAP.put(Rops.CMPG_DOUBLE,          Dops.CMPG_DOUBLE);
    364         MAP.put(Rops.CONV_L2I,             Dops.LONG_TO_INT);
    365         MAP.put(Rops.CONV_F2I,             Dops.FLOAT_TO_INT);
    366         MAP.put(Rops.CONV_D2I,             Dops.DOUBLE_TO_INT);
    367         MAP.put(Rops.CONV_I2L,             Dops.INT_TO_LONG);
    368         MAP.put(Rops.CONV_F2L,             Dops.FLOAT_TO_LONG);
    369         MAP.put(Rops.CONV_D2L,             Dops.DOUBLE_TO_LONG);
    370         MAP.put(Rops.CONV_I2F,             Dops.INT_TO_FLOAT);
    371         MAP.put(Rops.CONV_L2F,             Dops.LONG_TO_FLOAT);
    372         MAP.put(Rops.CONV_D2F,             Dops.DOUBLE_TO_FLOAT);
    373         MAP.put(Rops.CONV_I2D,             Dops.INT_TO_DOUBLE);
    374         MAP.put(Rops.CONV_L2D,             Dops.LONG_TO_DOUBLE);
    375         MAP.put(Rops.CONV_F2D,             Dops.FLOAT_TO_DOUBLE);
    376         MAP.put(Rops.TO_BYTE,              Dops.INT_TO_BYTE);
    377         MAP.put(Rops.TO_CHAR,              Dops.INT_TO_CHAR);
    378         MAP.put(Rops.TO_SHORT,             Dops.INT_TO_SHORT);
    379         MAP.put(Rops.RETURN_VOID,          Dops.RETURN_VOID);
    380         MAP.put(Rops.RETURN_INT,           Dops.RETURN);
    381         MAP.put(Rops.RETURN_LONG,          Dops.RETURN_WIDE);
    382         MAP.put(Rops.RETURN_FLOAT,         Dops.RETURN);
    383         MAP.put(Rops.RETURN_DOUBLE,        Dops.RETURN_WIDE);
    384         MAP.put(Rops.RETURN_OBJECT,        Dops.RETURN_OBJECT);
    385         MAP.put(Rops.ARRAY_LENGTH,         Dops.ARRAY_LENGTH);
    386         MAP.put(Rops.THROW,                Dops.THROW);
    387         MAP.put(Rops.MONITOR_ENTER,        Dops.MONITOR_ENTER);
    388         MAP.put(Rops.MONITOR_EXIT,         Dops.MONITOR_EXIT);
    389         MAP.put(Rops.AGET_INT,             Dops.AGET);
    390         MAP.put(Rops.AGET_LONG,            Dops.AGET_WIDE);
    391         MAP.put(Rops.AGET_FLOAT,           Dops.AGET);
    392         MAP.put(Rops.AGET_DOUBLE,          Dops.AGET_WIDE);
    393         MAP.put(Rops.AGET_OBJECT,          Dops.AGET_OBJECT);
    394         MAP.put(Rops.AGET_BOOLEAN,         Dops.AGET_BOOLEAN);
    395         MAP.put(Rops.AGET_BYTE,            Dops.AGET_BYTE);
    396         MAP.put(Rops.AGET_CHAR,            Dops.AGET_CHAR);
    397         MAP.put(Rops.AGET_SHORT,           Dops.AGET_SHORT);
    398         MAP.put(Rops.APUT_INT,             Dops.APUT);
    399         MAP.put(Rops.APUT_LONG,            Dops.APUT_WIDE);
    400         MAP.put(Rops.APUT_FLOAT,           Dops.APUT);
    401         MAP.put(Rops.APUT_DOUBLE,          Dops.APUT_WIDE);
    402         MAP.put(Rops.APUT_OBJECT,          Dops.APUT_OBJECT);
    403         MAP.put(Rops.APUT_BOOLEAN,         Dops.APUT_BOOLEAN);
    404         MAP.put(Rops.APUT_BYTE,            Dops.APUT_BYTE);
    405         MAP.put(Rops.APUT_CHAR,            Dops.APUT_CHAR);
    406         MAP.put(Rops.APUT_SHORT,           Dops.APUT_SHORT);
    407         MAP.put(Rops.NEW_INSTANCE,         Dops.NEW_INSTANCE);
    408         MAP.put(Rops.CHECK_CAST,           Dops.CHECK_CAST);
    409         MAP.put(Rops.INSTANCE_OF,          Dops.INSTANCE_OF);
    410 
    411         MAP.put(Rops.GET_FIELD_LONG,       Dops.IGET_WIDE);
    412         MAP.put(Rops.GET_FIELD_FLOAT,      Dops.IGET);
    413         MAP.put(Rops.GET_FIELD_DOUBLE,     Dops.IGET_WIDE);
    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 
    420         MAP.put(Rops.GET_STATIC_LONG,      Dops.SGET_WIDE);
    421         MAP.put(Rops.GET_STATIC_FLOAT,     Dops.SGET);
    422         MAP.put(Rops.GET_STATIC_DOUBLE,    Dops.SGET_WIDE);
    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 
    429         MAP.put(Rops.PUT_FIELD_LONG,       Dops.IPUT_WIDE);
    430         MAP.put(Rops.PUT_FIELD_FLOAT,      Dops.IPUT);
    431         MAP.put(Rops.PUT_FIELD_DOUBLE,     Dops.IPUT_WIDE);
    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 
    438         MAP.put(Rops.PUT_STATIC_LONG,      Dops.SPUT_WIDE);
    439         MAP.put(Rops.PUT_STATIC_FLOAT,     Dops.SPUT);
    440         MAP.put(Rops.PUT_STATIC_DOUBLE,    Dops.SPUT_WIDE);
    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      */
    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