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.rop.code;
     18 
     19 import com.android.dx.rop.cst.Constant;
     20 import com.android.dx.rop.cst.CstBaseMethodRef;
     21 import com.android.dx.rop.cst.CstMethodRef;
     22 import com.android.dx.rop.cst.CstType;
     23 import com.android.dx.rop.type.Prototype;
     24 import com.android.dx.rop.type.StdTypeList;
     25 import com.android.dx.rop.type.Type;
     26 import com.android.dx.rop.type.TypeBearer;
     27 import com.android.dx.rop.type.TypeList;
     28 
     29 /**
     30  * Standard instances of {@link Rop}.
     31  */
     32 public final class Rops {
     33     /** {@code nop()} */
     34     public static final Rop NOP =
     35         new Rop(RegOps.NOP, Type.VOID, StdTypeList.EMPTY, "nop");
     36 
     37     /** {@code r,x: int :: r = x;} */
     38     public static final Rop MOVE_INT =
     39         new Rop(RegOps.MOVE, Type.INT, StdTypeList.INT, "move-int");
     40 
     41     /** {@code r,x: long :: r = x;} */
     42     public static final Rop MOVE_LONG =
     43         new Rop(RegOps.MOVE, Type.LONG, StdTypeList.LONG, "move-long");
     44 
     45     /** {@code r,x: float :: r = x;} */
     46     public static final Rop MOVE_FLOAT =
     47         new Rop(RegOps.MOVE, Type.FLOAT, StdTypeList.FLOAT, "move-float");
     48 
     49     /** {@code r,x: double :: r = x;} */
     50     public static final Rop MOVE_DOUBLE =
     51         new Rop(RegOps.MOVE, Type.DOUBLE, StdTypeList.DOUBLE, "move-double");
     52 
     53     /** {@code r,x: Object :: r = x;} */
     54     public static final Rop MOVE_OBJECT =
     55         new Rop(RegOps.MOVE, Type.OBJECT, StdTypeList.OBJECT, "move-object");
     56 
     57     /**
     58      * {@code r,x: ReturnAddress :: r = x;}
     59      *
     60      * Note that this rop-form instruction has no dex-form equivilent and
     61      * must be removed before the dex conversion.
     62      */
     63     public static final Rop MOVE_RETURN_ADDRESS =
     64         new Rop(RegOps.MOVE, Type.RETURN_ADDRESS,
     65                 StdTypeList.RETURN_ADDRESS, "move-return-address");
     66 
     67     /** {@code r,param(x): int :: r = param(x);} */
     68     public static final Rop MOVE_PARAM_INT =
     69         new Rop(RegOps.MOVE_PARAM, Type.INT, StdTypeList.EMPTY,
     70                 "move-param-int");
     71 
     72     /** {@code r,param(x): long :: r = param(x);} */
     73     public static final Rop MOVE_PARAM_LONG =
     74         new Rop(RegOps.MOVE_PARAM, Type.LONG, StdTypeList.EMPTY,
     75                 "move-param-long");
     76 
     77     /** {@code r,param(x): float :: r = param(x);} */
     78     public static final Rop MOVE_PARAM_FLOAT =
     79         new Rop(RegOps.MOVE_PARAM, Type.FLOAT, StdTypeList.EMPTY,
     80                 "move-param-float");
     81 
     82     /** {@code r,param(x): double :: r = param(x);} */
     83     public static final Rop MOVE_PARAM_DOUBLE =
     84         new Rop(RegOps.MOVE_PARAM, Type.DOUBLE, StdTypeList.EMPTY,
     85                 "move-param-double");
     86 
     87     /** {@code r,param(x): Object :: r = param(x);} */
     88     public static final Rop MOVE_PARAM_OBJECT =
     89         new Rop(RegOps.MOVE_PARAM, Type.OBJECT, StdTypeList.EMPTY,
     90                 "move-param-object");
     91 
     92     /** {@code r, literal: int :: r = literal;} */
     93     public static final Rop CONST_INT =
     94         new Rop(RegOps.CONST, Type.INT, StdTypeList.EMPTY, "const-int");
     95 
     96     /** {@code r, literal: long :: r = literal;} */
     97     public static final Rop CONST_LONG =
     98         new Rop(RegOps.CONST, Type.LONG, StdTypeList.EMPTY, "const-long");
     99 
    100     /** {@code r, literal: float :: r = literal;} */
    101     public static final Rop CONST_FLOAT =
    102         new Rop(RegOps.CONST, Type.FLOAT, StdTypeList.EMPTY, "const-float");
    103 
    104     /** {@code r, literal: double :: r = literal;} */
    105     public static final Rop CONST_DOUBLE =
    106         new Rop(RegOps.CONST, Type.DOUBLE, StdTypeList.EMPTY, "const-double");
    107 
    108     /** {@code r, literal: Object :: r = literal;} */
    109     public static final Rop CONST_OBJECT =
    110         new Rop(RegOps.CONST, Type.OBJECT, StdTypeList.EMPTY,
    111                 Exceptions.LIST_Error, "const-object");
    112 
    113     /** {@code r, literal: Object :: r = literal;} */
    114     public static final Rop CONST_OBJECT_NOTHROW =
    115         new Rop(RegOps.CONST, Type.OBJECT, StdTypeList.EMPTY,
    116                 "const-object-nothrow");
    117 
    118     /** {@code goto label} */
    119     public static final Rop GOTO =
    120         new Rop(RegOps.GOTO, Type.VOID, StdTypeList.EMPTY, Rop.BRANCH_GOTO,
    121                 "goto");
    122 
    123     /** {@code x: int :: if (x == 0) goto label} */
    124     public static final Rop IF_EQZ_INT =
    125         new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
    126                 "if-eqz-int");
    127 
    128     /** {@code x: int :: if (x != 0) goto label} */
    129     public static final Rop IF_NEZ_INT =
    130         new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
    131                 "if-nez-int");
    132 
    133     /** {@code x: int :: if (x < 0) goto label} */
    134     public static final Rop IF_LTZ_INT =
    135         new Rop(RegOps.IF_LT, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
    136                 "if-ltz-int");
    137 
    138     /** {@code x: int :: if (x >= 0) goto label} */
    139     public static final Rop IF_GEZ_INT =
    140         new Rop(RegOps.IF_GE, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
    141                 "if-gez-int");
    142 
    143     /** {@code x: int :: if (x <= 0) goto label} */
    144     public static final Rop IF_LEZ_INT =
    145         new Rop(RegOps.IF_LE, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
    146                 "if-lez-int");
    147 
    148     /** {@code x: int :: if (x > 0) goto label} */
    149     public static final Rop IF_GTZ_INT =
    150         new Rop(RegOps.IF_GT, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
    151                 "if-gtz-int");
    152 
    153     /** {@code x: Object :: if (x == null) goto label} */
    154     public static final Rop IF_EQZ_OBJECT =
    155         new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.OBJECT, Rop.BRANCH_IF,
    156                 "if-eqz-object");
    157 
    158     /** {@code x: Object :: if (x != null) goto label} */
    159     public static final Rop IF_NEZ_OBJECT =
    160         new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.OBJECT, Rop.BRANCH_IF,
    161                 "if-nez-object");
    162 
    163     /** {@code x,y: int :: if (x == y) goto label} */
    164     public static final Rop IF_EQ_INT =
    165         new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
    166                 "if-eq-int");
    167 
    168     /** {@code x,y: int :: if (x != y) goto label} */
    169     public static final Rop IF_NE_INT =
    170         new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
    171                 "if-ne-int");
    172 
    173     /** {@code x,y: int :: if (x < y) goto label} */
    174     public static final Rop IF_LT_INT =
    175         new Rop(RegOps.IF_LT, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
    176                 "if-lt-int");
    177 
    178     /** {@code x,y: int :: if (x >= y) goto label} */
    179     public static final Rop IF_GE_INT =
    180         new Rop(RegOps.IF_GE, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
    181                 "if-ge-int");
    182 
    183     /** {@code x,y: int :: if (x <= y) goto label} */
    184     public static final Rop IF_LE_INT =
    185         new Rop(RegOps.IF_LE, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
    186                 "if-le-int");
    187 
    188     /** {@code x,y: int :: if (x > y) goto label} */
    189     public static final Rop IF_GT_INT =
    190         new Rop(RegOps.IF_GT, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
    191                 "if-gt-int");
    192 
    193     /** {@code x,y: Object :: if (x == y) goto label} */
    194     public static final Rop IF_EQ_OBJECT =
    195         new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.OBJECT_OBJECT,
    196                 Rop.BRANCH_IF, "if-eq-object");
    197 
    198     /** {@code x,y: Object :: if (x != y) goto label} */
    199     public static final Rop IF_NE_OBJECT =
    200         new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.OBJECT_OBJECT,
    201                 Rop.BRANCH_IF, "if-ne-object");
    202 
    203     /** {@code x: int :: goto switchtable[x]} */
    204     public static final Rop SWITCH =
    205         new Rop(RegOps.SWITCH, Type.VOID, StdTypeList.INT, Rop.BRANCH_SWITCH,
    206                 "switch");
    207 
    208     /** {@code r,x,y: int :: r = x + y;} */
    209     public static final Rop ADD_INT =
    210         new Rop(RegOps.ADD, Type.INT, StdTypeList.INT_INT, "add-int");
    211 
    212     /** {@code r,x,y: long :: r = x + y;} */
    213     public static final Rop ADD_LONG =
    214         new Rop(RegOps.ADD, Type.LONG, StdTypeList.LONG_LONG, "add-long");
    215 
    216     /** {@code r,x,y: float :: r = x + y;} */
    217     public static final Rop ADD_FLOAT =
    218         new Rop(RegOps.ADD, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "add-float");
    219 
    220     /** {@code r,x,y: double :: r = x + y;} */
    221     public static final Rop ADD_DOUBLE =
    222         new Rop(RegOps.ADD, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE,
    223                 Rop.BRANCH_NONE, "add-double");
    224 
    225     /** {@code r,x,y: int :: r = x - y;} */
    226     public static final Rop SUB_INT =
    227         new Rop(RegOps.SUB, Type.INT, StdTypeList.INT_INT, "sub-int");
    228 
    229     /** {@code r,x,y: long :: r = x - y;} */
    230     public static final Rop SUB_LONG =
    231         new Rop(RegOps.SUB, Type.LONG, StdTypeList.LONG_LONG, "sub-long");
    232 
    233     /** {@code r,x,y: float :: r = x - y;} */
    234     public static final Rop SUB_FLOAT =
    235         new Rop(RegOps.SUB, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "sub-float");
    236 
    237     /** {@code r,x,y: double :: r = x - y;} */
    238     public static final Rop SUB_DOUBLE =
    239         new Rop(RegOps.SUB, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE,
    240                 Rop.BRANCH_NONE, "sub-double");
    241 
    242     /** {@code r,x,y: int :: r = x * y;} */
    243     public static final Rop MUL_INT =
    244         new Rop(RegOps.MUL, Type.INT, StdTypeList.INT_INT, "mul-int");
    245 
    246     /** {@code r,x,y: long :: r = x * y;} */
    247     public static final Rop MUL_LONG =
    248         new Rop(RegOps.MUL, Type.LONG, StdTypeList.LONG_LONG, "mul-long");
    249 
    250     /** {@code r,x,y: float :: r = x * y;} */
    251     public static final Rop MUL_FLOAT =
    252         new Rop(RegOps.MUL, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "mul-float");
    253 
    254     /** {@code r,x,y: double :: r = x * y;} */
    255     public static final Rop MUL_DOUBLE =
    256         new Rop(RegOps.MUL, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE,
    257                 Rop.BRANCH_NONE, "mul-double");
    258 
    259     /** {@code r,x,y: int :: r = x / y;} */
    260     public static final Rop DIV_INT =
    261         new Rop(RegOps.DIV, Type.INT, StdTypeList.INT_INT,
    262                 Exceptions.LIST_Error_ArithmeticException, "div-int");
    263 
    264     /** {@code r,x,y: long :: r = x / y;} */
    265     public static final Rop DIV_LONG =
    266         new Rop(RegOps.DIV, Type.LONG, StdTypeList.LONG_LONG,
    267                 Exceptions.LIST_Error_ArithmeticException, "div-long");
    268 
    269     /** {@code r,x,y: float :: r = x / y;} */
    270     public static final Rop DIV_FLOAT =
    271         new Rop(RegOps.DIV, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "div-float");
    272 
    273     /** {@code r,x,y: double :: r = x / y;} */
    274     public static final Rop DIV_DOUBLE =
    275         new Rop(RegOps.DIV, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE,
    276                 "div-double");
    277 
    278     /** {@code r,x,y: int :: r = x % y;} */
    279     public static final Rop REM_INT =
    280         new Rop(RegOps.REM, Type.INT, StdTypeList.INT_INT,
    281                 Exceptions.LIST_Error_ArithmeticException, "rem-int");
    282 
    283     /** {@code r,x,y: long :: r = x % y;} */
    284     public static final Rop REM_LONG =
    285         new Rop(RegOps.REM, Type.LONG, StdTypeList.LONG_LONG,
    286                 Exceptions.LIST_Error_ArithmeticException, "rem-long");
    287 
    288     /** {@code r,x,y: float :: r = x % y;} */
    289     public static final Rop REM_FLOAT =
    290         new Rop(RegOps.REM, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "rem-float");
    291 
    292     /** {@code r,x,y: double :: r = x % y;} */
    293     public static final Rop REM_DOUBLE =
    294         new Rop(RegOps.REM, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE,
    295                 "rem-double");
    296 
    297     /** {@code r,x: int :: r = -x;} */
    298     public static final Rop NEG_INT =
    299         new Rop(RegOps.NEG, Type.INT, StdTypeList.INT, "neg-int");
    300 
    301     /** {@code r,x: long :: r = -x;} */
    302     public static final Rop NEG_LONG =
    303         new Rop(RegOps.NEG, Type.LONG, StdTypeList.LONG, "neg-long");
    304 
    305     /** {@code r,x: float :: r = -x;} */
    306     public static final Rop NEG_FLOAT =
    307         new Rop(RegOps.NEG, Type.FLOAT, StdTypeList.FLOAT, "neg-float");
    308 
    309     /** {@code r,x: double :: r = -x;} */
    310     public static final Rop NEG_DOUBLE =
    311         new Rop(RegOps.NEG, Type.DOUBLE, StdTypeList.DOUBLE, "neg-double");
    312 
    313     /** {@code r,x,y: int :: r = x & y;} */
    314     public static final Rop AND_INT =
    315         new Rop(RegOps.AND, Type.INT, StdTypeList.INT_INT, "and-int");
    316 
    317     /** {@code r,x,y: long :: r = x & y;} */
    318     public static final Rop AND_LONG =
    319         new Rop(RegOps.AND, Type.LONG, StdTypeList.LONG_LONG, "and-long");
    320 
    321     /** {@code r,x,y: int :: r = x | y;} */
    322     public static final Rop OR_INT =
    323         new Rop(RegOps.OR, Type.INT, StdTypeList.INT_INT, "or-int");
    324 
    325     /** {@code r,x,y: long :: r = x | y;} */
    326     public static final Rop OR_LONG =
    327         new Rop(RegOps.OR, Type.LONG, StdTypeList.LONG_LONG, "or-long");
    328 
    329     /** {@code r,x,y: int :: r = x ^ y;} */
    330     public static final Rop XOR_INT =
    331         new Rop(RegOps.XOR, Type.INT, StdTypeList.INT_INT, "xor-int");
    332 
    333     /** {@code r,x,y: long :: r = x ^ y;} */
    334     public static final Rop XOR_LONG =
    335         new Rop(RegOps.XOR, Type.LONG, StdTypeList.LONG_LONG, "xor-long");
    336 
    337     /** {@code r,x,y: int :: r = x << y;} */
    338     public static final Rop SHL_INT =
    339         new Rop(RegOps.SHL, Type.INT, StdTypeList.INT_INT, "shl-int");
    340 
    341     /** {@code r,x: long; y: int :: r = x << y;} */
    342     public static final Rop SHL_LONG =
    343         new Rop(RegOps.SHL, Type.LONG, StdTypeList.LONG_INT, "shl-long");
    344 
    345     /** {@code r,x,y: int :: r = x >> y;} */
    346     public static final Rop SHR_INT =
    347         new Rop(RegOps.SHR, Type.INT, StdTypeList.INT_INT, "shr-int");
    348 
    349     /** {@code r,x: long; y: int :: r = x >> y;} */
    350     public static final Rop SHR_LONG =
    351         new Rop(RegOps.SHR, Type.LONG, StdTypeList.LONG_INT, "shr-long");
    352 
    353     /** {@code r,x,y: int :: r = x >>> y;} */
    354     public static final Rop USHR_INT =
    355         new Rop(RegOps.USHR, Type.INT, StdTypeList.INT_INT, "ushr-int");
    356 
    357     /** {@code r,x: long; y: int :: r = x >>> y;} */
    358     public static final Rop USHR_LONG =
    359         new Rop(RegOps.USHR, Type.LONG, StdTypeList.LONG_INT, "ushr-long");
    360 
    361     /** {@code r,x: int :: r = ~x;} */
    362     public static final Rop NOT_INT =
    363         new Rop(RegOps.NOT, Type.INT, StdTypeList.INT, "not-int");
    364 
    365     /** {@code r,x: long :: r = ~x;} */
    366     public static final Rop NOT_LONG =
    367         new Rop(RegOps.NOT, Type.LONG, StdTypeList.LONG, "not-long");
    368 
    369     /** {@code r,x,c: int :: r = x + c;} */
    370     public static final Rop ADD_CONST_INT =
    371         new Rop(RegOps.ADD, Type.INT, StdTypeList.INT, "add-const-int");
    372 
    373     /** {@code r,x,c: long :: r = x + c;} */
    374     public static final Rop ADD_CONST_LONG =
    375         new Rop(RegOps.ADD, Type.LONG, StdTypeList.LONG, "add-const-long");
    376 
    377     /** {@code r,x,c: float :: r = x + c;} */
    378     public static final Rop ADD_CONST_FLOAT =
    379         new Rop(RegOps.ADD, Type.FLOAT, StdTypeList.FLOAT, "add-const-float");
    380 
    381     /** {@code r,x,c: double :: r = x + c;} */
    382     public static final Rop ADD_CONST_DOUBLE =
    383         new Rop(RegOps.ADD, Type.DOUBLE, StdTypeList.DOUBLE,
    384                 "add-const-double");
    385 
    386     /** {@code r,x,c: int :: r = x - c;} */
    387     public static final Rop SUB_CONST_INT =
    388         new Rop(RegOps.SUB, Type.INT, StdTypeList.INT, "sub-const-int");
    389 
    390     /** {@code r,x,c: long :: r = x - c;} */
    391     public static final Rop SUB_CONST_LONG =
    392         new Rop(RegOps.SUB, Type.LONG, StdTypeList.LONG, "sub-const-long");
    393 
    394     /** {@code r,x,c: float :: r = x - c;} */
    395     public static final Rop SUB_CONST_FLOAT =
    396         new Rop(RegOps.SUB, Type.FLOAT, StdTypeList.FLOAT, "sub-const-float");
    397 
    398     /** {@code r,x,c: double :: r = x - c;} */
    399     public static final Rop SUB_CONST_DOUBLE =
    400         new Rop(RegOps.SUB, Type.DOUBLE, StdTypeList.DOUBLE,
    401                 "sub-const-double");
    402 
    403     /** {@code r,x,c: int :: r = x * c;} */
    404     public static final Rop MUL_CONST_INT =
    405         new Rop(RegOps.MUL, Type.INT, StdTypeList.INT, "mul-const-int");
    406 
    407     /** {@code r,x,c: long :: r = x * c;} */
    408     public static final Rop MUL_CONST_LONG =
    409         new Rop(RegOps.MUL, Type.LONG, StdTypeList.LONG, "mul-const-long");
    410 
    411     /** {@code r,x,c: float :: r = x * c;} */
    412     public static final Rop MUL_CONST_FLOAT =
    413         new Rop(RegOps.MUL, Type.FLOAT, StdTypeList.FLOAT, "mul-const-float");
    414 
    415     /** {@code r,x,c: double :: r = x * c;} */
    416     public static final Rop MUL_CONST_DOUBLE =
    417         new Rop(RegOps.MUL, Type.DOUBLE, StdTypeList.DOUBLE,
    418                 "mul-const-double");
    419 
    420     /** {@code r,x,c: int :: r = x / c;} */
    421     public static final Rop DIV_CONST_INT =
    422         new Rop(RegOps.DIV, Type.INT, StdTypeList.INT,
    423                 Exceptions.LIST_Error_ArithmeticException, "div-const-int");
    424 
    425     /** {@code r,x,c: long :: r = x / c;} */
    426     public static final Rop DIV_CONST_LONG =
    427         new Rop(RegOps.DIV, Type.LONG, StdTypeList.LONG,
    428                 Exceptions.LIST_Error_ArithmeticException, "div-const-long");
    429 
    430     /** {@code r,x,c: float :: r = x / c;} */
    431     public static final Rop DIV_CONST_FLOAT =
    432         new Rop(RegOps.DIV, Type.FLOAT, StdTypeList.FLOAT, "div-const-float");
    433 
    434     /** {@code r,x,c: double :: r = x / c;} */
    435     public static final Rop DIV_CONST_DOUBLE =
    436         new Rop(RegOps.DIV, Type.DOUBLE, StdTypeList.DOUBLE,
    437                 "div-const-double");
    438 
    439     /** {@code r,x,c: int :: r = x % c;} */
    440     public static final Rop REM_CONST_INT =
    441         new Rop(RegOps.REM, Type.INT, StdTypeList.INT,
    442                 Exceptions.LIST_Error_ArithmeticException, "rem-const-int");
    443 
    444     /** {@code r,x,c: long :: r = x % c;} */
    445     public static final Rop REM_CONST_LONG =
    446         new Rop(RegOps.REM, Type.LONG, StdTypeList.LONG,
    447                 Exceptions.LIST_Error_ArithmeticException, "rem-const-long");
    448 
    449     /** {@code r,x,c: float :: r = x % c;} */
    450     public static final Rop REM_CONST_FLOAT =
    451         new Rop(RegOps.REM, Type.FLOAT, StdTypeList.FLOAT, "rem-const-float");
    452 
    453     /** {@code r,x,c: double :: r = x % c;} */
    454     public static final Rop REM_CONST_DOUBLE =
    455         new Rop(RegOps.REM, Type.DOUBLE, StdTypeList.DOUBLE,
    456                 "rem-const-double");
    457 
    458     /** {@code r,x,c: int :: r = x & c;} */
    459     public static final Rop AND_CONST_INT =
    460         new Rop(RegOps.AND, Type.INT, StdTypeList.INT, "and-const-int");
    461 
    462     /** {@code r,x,c: long :: r = x & c;} */
    463     public static final Rop AND_CONST_LONG =
    464         new Rop(RegOps.AND, Type.LONG, StdTypeList.LONG, "and-const-long");
    465 
    466     /** {@code r,x,c: int :: r = x | c;} */
    467     public static final Rop OR_CONST_INT =
    468         new Rop(RegOps.OR, Type.INT, StdTypeList.INT, "or-const-int");
    469 
    470     /** {@code r,x,c: long :: r = x | c;} */
    471     public static final Rop OR_CONST_LONG =
    472         new Rop(RegOps.OR, Type.LONG, StdTypeList.LONG, "or-const-long");
    473 
    474     /** {@code r,x,c: int :: r = x ^ c;} */
    475     public static final Rop XOR_CONST_INT =
    476         new Rop(RegOps.XOR, Type.INT, StdTypeList.INT, "xor-const-int");
    477 
    478     /** {@code r,x,c: long :: r = x ^ c;} */
    479     public static final Rop XOR_CONST_LONG =
    480         new Rop(RegOps.XOR, Type.LONG, StdTypeList.LONG, "xor-const-long");
    481 
    482     /** {@code r,x,c: int :: r = x << c;} */
    483     public static final Rop SHL_CONST_INT =
    484         new Rop(RegOps.SHL, Type.INT, StdTypeList.INT, "shl-const-int");
    485 
    486     /** {@code r,x: long; c: int :: r = x << c;} */
    487     public static final Rop SHL_CONST_LONG =
    488         new Rop(RegOps.SHL, Type.LONG, StdTypeList.INT, "shl-const-long");
    489 
    490     /** {@code r,x,c: int :: r = x >> c;} */
    491     public static final Rop SHR_CONST_INT =
    492         new Rop(RegOps.SHR, Type.INT, StdTypeList.INT, "shr-const-int");
    493 
    494     /** {@code r,x: long; c: int :: r = x >> c;} */
    495     public static final Rop SHR_CONST_LONG =
    496         new Rop(RegOps.SHR, Type.LONG, StdTypeList.INT, "shr-const-long");
    497 
    498     /** {@code r,x,c: int :: r = x >>> c;} */
    499     public static final Rop USHR_CONST_INT =
    500         new Rop(RegOps.USHR, Type.INT, StdTypeList.INT, "ushr-const-int");
    501 
    502     /** {@code r,x: long; c: int :: r = x >>> c;} */
    503     public static final Rop USHR_CONST_LONG =
    504         new Rop(RegOps.USHR, Type.LONG, StdTypeList.INT, "ushr-const-long");
    505 
    506     /** {@code r: int; x,y: long :: r = cmp(x, y);} */
    507     public static final Rop CMPL_LONG =
    508         new Rop(RegOps.CMPL, Type.INT, StdTypeList.LONG_LONG, "cmpl-long");
    509 
    510     /** {@code r: int; x,y: float :: r = cmpl(x, y);} */
    511     public static final Rop CMPL_FLOAT =
    512         new Rop(RegOps.CMPL, Type.INT, StdTypeList.FLOAT_FLOAT, "cmpl-float");
    513 
    514     /** {@code r: int; x,y: double :: r = cmpl(x, y);} */
    515     public static final Rop CMPL_DOUBLE =
    516         new Rop(RegOps.CMPL, Type.INT, StdTypeList.DOUBLE_DOUBLE,
    517                 "cmpl-double");
    518 
    519     /** {@code r: int; x,y: float :: r = cmpg(x, y);} */
    520     public static final Rop CMPG_FLOAT =
    521         new Rop(RegOps.CMPG, Type.INT, StdTypeList.FLOAT_FLOAT, "cmpg-float");
    522 
    523     /** {@code r: int; x,y: double :: r = cmpg(x, y);} */
    524     public static final Rop CMPG_DOUBLE =
    525         new Rop(RegOps.CMPG, Type.INT, StdTypeList.DOUBLE_DOUBLE,
    526                 "cmpg-double");
    527 
    528     /** {@code r: int; x: long :: r = (int) x} */
    529     public static final Rop CONV_L2I =
    530         new Rop(RegOps.CONV, Type.INT, StdTypeList.LONG, "conv-l2i");
    531 
    532     /** {@code r: int; x: float :: r = (int) x} */
    533     public static final Rop CONV_F2I =
    534         new Rop(RegOps.CONV, Type.INT, StdTypeList.FLOAT, "conv-f2i");
    535 
    536     /** {@code r: int; x: double :: r = (int) x} */
    537     public static final Rop CONV_D2I =
    538         new Rop(RegOps.CONV, Type.INT, StdTypeList.DOUBLE, "conv-d2i");
    539 
    540     /** {@code r: long; x: int :: r = (long) x} */
    541     public static final Rop CONV_I2L =
    542         new Rop(RegOps.CONV, Type.LONG, StdTypeList.INT, "conv-i2l");
    543 
    544     /** {@code r: long; x: float :: r = (long) x} */
    545     public static final Rop CONV_F2L =
    546         new Rop(RegOps.CONV, Type.LONG, StdTypeList.FLOAT, "conv-f2l");
    547 
    548     /** {@code r: long; x: double :: r = (long) x} */
    549     public static final Rop CONV_D2L =
    550         new Rop(RegOps.CONV, Type.LONG, StdTypeList.DOUBLE, "conv-d2l");
    551 
    552     /** {@code r: float; x: int :: r = (float) x} */
    553     public static final Rop CONV_I2F =
    554         new Rop(RegOps.CONV, Type.FLOAT, StdTypeList.INT, "conv-i2f");
    555 
    556     /** {@code r: float; x: long :: r = (float) x} */
    557     public static final Rop CONV_L2F =
    558         new Rop(RegOps.CONV, Type.FLOAT, StdTypeList.LONG, "conv-l2f");
    559 
    560     /** {@code r: float; x: double :: r = (float) x} */
    561     public static final Rop CONV_D2F =
    562         new Rop(RegOps.CONV, Type.FLOAT, StdTypeList.DOUBLE, "conv-d2f");
    563 
    564     /** {@code r: double; x: int :: r = (double) x} */
    565     public static final Rop CONV_I2D =
    566         new Rop(RegOps.CONV, Type.DOUBLE, StdTypeList.INT, "conv-i2d");
    567 
    568     /** {@code r: double; x: long :: r = (double) x} */
    569     public static final Rop CONV_L2D =
    570         new Rop(RegOps.CONV, Type.DOUBLE, StdTypeList.LONG, "conv-l2d");
    571 
    572     /** {@code r: double; x: float :: r = (double) x} */
    573     public static final Rop CONV_F2D =
    574         new Rop(RegOps.CONV, Type.DOUBLE, StdTypeList.FLOAT, "conv-f2d");
    575 
    576     /**
    577      * {@code r,x: int :: r = (x << 24) >> 24} (Java-style
    578      * convert int to byte)
    579      */
    580     public static final Rop TO_BYTE =
    581         new Rop(RegOps.TO_BYTE, Type.INT, StdTypeList.INT, "to-byte");
    582 
    583     /**
    584      * {@code r,x: int :: r = x & 0xffff} (Java-style
    585      * convert int to char)
    586      */
    587     public static final Rop TO_CHAR =
    588         new Rop(RegOps.TO_CHAR, Type.INT, StdTypeList.INT, "to-char");
    589 
    590     /**
    591      * {@code r,x: int :: r = (x << 16) >> 16} (Java-style
    592      * convert int to short)
    593      */
    594     public static final Rop TO_SHORT =
    595         new Rop(RegOps.TO_SHORT, Type.INT, StdTypeList.INT, "to-short");
    596 
    597     /** {@code return void} */
    598     public static final Rop RETURN_VOID =
    599         new Rop(RegOps.RETURN, Type.VOID, StdTypeList.EMPTY, Rop.BRANCH_RETURN,
    600                 "return-void");
    601 
    602     /** {@code x: int; return x} */
    603     public static final Rop RETURN_INT =
    604         new Rop(RegOps.RETURN, Type.VOID, StdTypeList.INT, Rop.BRANCH_RETURN,
    605                 "return-int");
    606 
    607     /** {@code x: long; return x} */
    608     public static final Rop RETURN_LONG =
    609         new Rop(RegOps.RETURN, Type.VOID, StdTypeList.LONG, Rop.BRANCH_RETURN,
    610                 "return-long");
    611 
    612     /** {@code x: float; return x} */
    613     public static final Rop RETURN_FLOAT =
    614         new Rop(RegOps.RETURN, Type.VOID, StdTypeList.FLOAT, Rop.BRANCH_RETURN,
    615                 "return-float");
    616 
    617     /** {@code x: double; return x} */
    618     public static final Rop RETURN_DOUBLE =
    619         new Rop(RegOps.RETURN, Type.VOID, StdTypeList.DOUBLE,
    620                 Rop.BRANCH_RETURN, "return-double");
    621 
    622     /** {@code x: Object; return x} */
    623     public static final Rop RETURN_OBJECT =
    624         new Rop(RegOps.RETURN, Type.VOID, StdTypeList.OBJECT,
    625                 Rop.BRANCH_RETURN, "return-object");
    626 
    627     /** {@code T: any type; r: int; x: T[]; :: r = x.length} */
    628     public static final Rop ARRAY_LENGTH =
    629         new Rop(RegOps.ARRAY_LENGTH, Type.INT, StdTypeList.OBJECT,
    630                 Exceptions.LIST_Error_NullPointerException, "array-length");
    631 
    632     /** {@code x: Throwable :: throw(x)} */
    633     public static final Rop THROW =
    634         new Rop(RegOps.THROW, Type.VOID, StdTypeList.THROWABLE,
    635                 StdTypeList.THROWABLE, "throw");
    636 
    637     /** {@code x: Object :: monitorenter(x)} */
    638     public static final Rop MONITOR_ENTER =
    639         new Rop(RegOps.MONITOR_ENTER, Type.VOID, StdTypeList.OBJECT,
    640                 Exceptions.LIST_Error_NullPointerException, "monitor-enter");
    641 
    642     /** {@code x: Object :: monitorexit(x)} */
    643     public static final Rop MONITOR_EXIT =
    644         new Rop(RegOps.MONITOR_EXIT, Type.VOID, StdTypeList.OBJECT,
    645                 Exceptions.LIST_Error_Null_IllegalMonitorStateException,
    646                 "monitor-exit");
    647 
    648     /** {@code r,y: int; x: int[] :: r = x[y]} */
    649     public static final Rop AGET_INT =
    650         new Rop(RegOps.AGET, Type.INT, StdTypeList.INTARR_INT,
    651                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
    652                 "aget-int");
    653 
    654     /** {@code r: long; x: long[]; y: int :: r = x[y]} */
    655     public static final Rop AGET_LONG =
    656         new Rop(RegOps.AGET, Type.LONG, StdTypeList.LONGARR_INT,
    657                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
    658                 "aget-long");
    659 
    660     /** {@code r: float; x: float[]; y: int :: r = x[y]} */
    661     public static final Rop AGET_FLOAT =
    662         new Rop(RegOps.AGET, Type.FLOAT, StdTypeList.FLOATARR_INT,
    663                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
    664                 "aget-float");
    665 
    666     /** {@code r: double; x: double[]; y: int :: r = x[y]} */
    667     public static final Rop AGET_DOUBLE =
    668         new Rop(RegOps.AGET, Type.DOUBLE, StdTypeList.DOUBLEARR_INT,
    669                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
    670                 "aget-double");
    671 
    672     /** {@code r: Object; x: Object[]; y: int :: r = x[y]} */
    673     public static final Rop AGET_OBJECT =
    674         new Rop(RegOps.AGET, Type.OBJECT, StdTypeList.OBJECTARR_INT,
    675                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
    676                 "aget-object");
    677 
    678     /** {@code r: boolean; x: boolean[]; y: int :: r = x[y]} */
    679     public static final Rop AGET_BOOLEAN =
    680         new Rop(RegOps.AGET, Type.INT, StdTypeList.BOOLEANARR_INT,
    681                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
    682                 "aget-boolean");
    683 
    684     /** {@code r: byte; x: byte[]; y: int :: r = x[y]} */
    685     public static final Rop AGET_BYTE =
    686         new Rop(RegOps.AGET, Type.INT, StdTypeList.BYTEARR_INT,
    687                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aget-byte");
    688 
    689     /** {@code r: char; x: char[]; y: int :: r = x[y]} */
    690     public static final Rop AGET_CHAR =
    691         new Rop(RegOps.AGET, Type.INT, StdTypeList.CHARARR_INT,
    692                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aget-char");
    693 
    694     /** {@code r: short; x: short[]; y: int :: r = x[y]} */
    695     public static final Rop AGET_SHORT =
    696         new Rop(RegOps.AGET, Type.INT, StdTypeList.SHORTARR_INT,
    697                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
    698                 "aget-short");
    699 
    700     /** {@code x,z: int; y: int[] :: y[z] = x} */
    701     public static final Rop APUT_INT =
    702         new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_INTARR_INT,
    703                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aput-int");
    704 
    705     /** {@code x: long; y: long[]; z: int :: y[z] = x} */
    706     public static final Rop APUT_LONG =
    707         new Rop(RegOps.APUT, Type.VOID, StdTypeList.LONG_LONGARR_INT,
    708                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aput-long");
    709 
    710     /** {@code x: float; y: float[]; z: int :: y[z] = x} */
    711     public static final Rop APUT_FLOAT =
    712         new Rop(RegOps.APUT, Type.VOID, StdTypeList.FLOAT_FLOATARR_INT,
    713                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
    714                 "aput-float");
    715 
    716     /** {@code x: double; y: double[]; z: int :: y[z] = x} */
    717     public static final Rop APUT_DOUBLE =
    718         new Rop(RegOps.APUT, Type.VOID, StdTypeList.DOUBLE_DOUBLEARR_INT,
    719                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
    720                 "aput-double");
    721 
    722     /** {@code x: Object; y: Object[]; z: int :: y[z] = x} */
    723     public static final Rop APUT_OBJECT =
    724         new Rop(RegOps.APUT, Type.VOID, StdTypeList.OBJECT_OBJECTARR_INT,
    725                 Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore,
    726                 "aput-object");
    727 
    728     /** {@code x: boolean; y: boolean[]; z: int :: y[z] = x} */
    729     public static final Rop APUT_BOOLEAN =
    730         new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_BOOLEANARR_INT,
    731                 Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore,
    732                 "aput-boolean");
    733 
    734     /** {@code x: byte; y: byte[]; z: int :: y[z] = x} */
    735     public static final Rop APUT_BYTE =
    736         new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_BYTEARR_INT,
    737                 Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore, "aput-byte");
    738 
    739     /** {@code x: char; y: char[]; z: int :: y[z] = x} */
    740     public static final Rop APUT_CHAR =
    741         new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_CHARARR_INT,
    742                 Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore, "aput-char");
    743 
    744     /** {@code x: short; y: short[]; z: int :: y[z] = x} */
    745     public static final Rop APUT_SHORT =
    746         new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_SHORTARR_INT,
    747                 Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore,
    748                 "aput-short");
    749 
    750     /**
    751      * {@code T: any non-array object type :: r =
    752      * alloc(T)} (allocate heap space for an object)
    753      */
    754     public static final Rop NEW_INSTANCE =
    755         new Rop(RegOps.NEW_INSTANCE, Type.OBJECT, StdTypeList.EMPTY,
    756                 Exceptions.LIST_Error, "new-instance");
    757 
    758     /** {@code r: int[]; x: int :: r = new int[x]} */
    759     public static final Rop NEW_ARRAY_INT =
    760         new Rop(RegOps.NEW_ARRAY, Type.INT_ARRAY, StdTypeList.INT,
    761                 Exceptions.LIST_Error_NegativeArraySizeException,
    762                 "new-array-int");
    763 
    764     /** {@code r: long[]; x: int :: r = new long[x]} */
    765     public static final Rop NEW_ARRAY_LONG =
    766         new Rop(RegOps.NEW_ARRAY, Type.LONG_ARRAY, StdTypeList.INT,
    767                 Exceptions.LIST_Error_NegativeArraySizeException,
    768                 "new-array-long");
    769 
    770     /** {@code r: float[]; x: int :: r = new float[x]} */
    771     public static final Rop NEW_ARRAY_FLOAT =
    772         new Rop(RegOps.NEW_ARRAY, Type.FLOAT_ARRAY, StdTypeList.INT,
    773                 Exceptions.LIST_Error_NegativeArraySizeException,
    774                 "new-array-float");
    775 
    776     /** {@code r: double[]; x: int :: r = new double[x]} */
    777     public static final Rop NEW_ARRAY_DOUBLE =
    778         new Rop(RegOps.NEW_ARRAY, Type.DOUBLE_ARRAY, StdTypeList.INT,
    779                 Exceptions.LIST_Error_NegativeArraySizeException,
    780                 "new-array-double");
    781 
    782     /** {@code r: boolean[]; x: int :: r = new boolean[x]} */
    783     public static final Rop NEW_ARRAY_BOOLEAN =
    784         new Rop(RegOps.NEW_ARRAY, Type.BOOLEAN_ARRAY, StdTypeList.INT,
    785                 Exceptions.LIST_Error_NegativeArraySizeException,
    786                 "new-array-boolean");
    787 
    788     /** {@code r: byte[]; x: int :: r = new byte[x]} */
    789     public static final Rop NEW_ARRAY_BYTE =
    790         new Rop(RegOps.NEW_ARRAY, Type.BYTE_ARRAY, StdTypeList.INT,
    791                 Exceptions.LIST_Error_NegativeArraySizeException,
    792                 "new-array-byte");
    793 
    794     /** {@code r: char[]; x: int :: r = new char[x]} */
    795     public static final Rop NEW_ARRAY_CHAR =
    796         new Rop(RegOps.NEW_ARRAY, Type.CHAR_ARRAY, StdTypeList.INT,
    797                 Exceptions.LIST_Error_NegativeArraySizeException,
    798                 "new-array-char");
    799 
    800     /** {@code r: short[]; x: int :: r = new short[x]} */
    801     public static final Rop NEW_ARRAY_SHORT =
    802         new Rop(RegOps.NEW_ARRAY, Type.SHORT_ARRAY, StdTypeList.INT,
    803                 Exceptions.LIST_Error_NegativeArraySizeException,
    804                 "new-array-short");
    805 
    806     /**
    807      * {@code T: any non-array object type; x: Object :: (T) x} (can
    808      * throw {@code ClassCastException})
    809      */
    810     public static final Rop CHECK_CAST =
    811         new Rop(RegOps.CHECK_CAST, Type.VOID, StdTypeList.OBJECT,
    812                 Exceptions.LIST_Error_ClassCastException, "check-cast");
    813 
    814     /**
    815      * {@code T: any non-array object type; x: Object :: x instanceof
    816      * T}. Note: This is listed as throwing {@code Error}
    817      * explicitly because the op <i>can</i> throw, but there are no
    818      * other predefined exceptions for it.
    819      */
    820     public static final Rop INSTANCE_OF =
    821         new Rop(RegOps.INSTANCE_OF, Type.INT, StdTypeList.OBJECT,
    822                 Exceptions.LIST_Error, "instance-of");
    823 
    824     /**
    825      * {@code r: int; x: Object; f: instance field spec of
    826      * type int :: r = x.f}
    827      */
    828     public static final Rop GET_FIELD_INT =
    829         new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT,
    830                 Exceptions.LIST_Error_NullPointerException, "get-field-int");
    831 
    832     /**
    833      * {@code r: long; x: Object; f: instance field spec of
    834      * type long :: r = x.f}
    835      */
    836     public static final Rop GET_FIELD_LONG =
    837         new Rop(RegOps.GET_FIELD, Type.LONG, StdTypeList.OBJECT,
    838                 Exceptions.LIST_Error_NullPointerException, "get-field-long");
    839 
    840     /**
    841      * {@code r: float; x: Object; f: instance field spec of
    842      * type float :: r = x.f}
    843      */
    844     public static final Rop GET_FIELD_FLOAT =
    845         new Rop(RegOps.GET_FIELD, Type.FLOAT, StdTypeList.OBJECT,
    846                 Exceptions.LIST_Error_NullPointerException,
    847                 "get-field-float");
    848 
    849     /**
    850      * {@code r: double; x: Object; f: instance field spec of
    851      * type double :: r = x.f}
    852      */
    853     public static final Rop GET_FIELD_DOUBLE =
    854         new Rop(RegOps.GET_FIELD, Type.DOUBLE, StdTypeList.OBJECT,
    855                 Exceptions.LIST_Error_NullPointerException,
    856                 "get-field-double");
    857 
    858     /**
    859      * {@code r: Object; x: Object; f: instance field spec of
    860      * type Object :: r = x.f}
    861      */
    862     public static final Rop GET_FIELD_OBJECT =
    863         new Rop(RegOps.GET_FIELD, Type.OBJECT, StdTypeList.OBJECT,
    864                 Exceptions.LIST_Error_NullPointerException,
    865                 "get-field-object");
    866 
    867     /**
    868      * {@code r: boolean; x: Object; f: instance field spec of
    869      * type boolean :: r = x.f}
    870      */
    871     public static final Rop GET_FIELD_BOOLEAN =
    872         new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT,
    873                 Exceptions.LIST_Error_NullPointerException,
    874                 "get-field-boolean");
    875 
    876     /**
    877      * {@code r: byte; x: Object; f: instance field spec of
    878      * type byte :: r = x.f}
    879      */
    880     public static final Rop GET_FIELD_BYTE =
    881         new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT,
    882                 Exceptions.LIST_Error_NullPointerException,
    883                 "get-field-byte");
    884 
    885     /**
    886      * {@code r: char; x: Object; f: instance field spec of
    887      * type char :: r = x.f}
    888      */
    889     public static final Rop GET_FIELD_CHAR =
    890         new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT,
    891                 Exceptions.LIST_Error_NullPointerException,
    892                 "get-field-char");
    893 
    894     /**
    895      * {@code r: short; x: Object; f: instance field spec of
    896      * type short :: r = x.f}
    897      */
    898     public static final Rop GET_FIELD_SHORT =
    899         new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT,
    900                 Exceptions.LIST_Error_NullPointerException,
    901                 "get-field-short");
    902 
    903     /** {@code r: int; f: static field spec of type int :: r = f} */
    904     public static final Rop GET_STATIC_INT =
    905         new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY,
    906                 Exceptions.LIST_Error, "get-static-int");
    907 
    908     /** {@code r: long; f: static field spec of type long :: r = f} */
    909     public static final Rop GET_STATIC_LONG =
    910         new Rop(RegOps.GET_STATIC, Type.LONG, StdTypeList.EMPTY,
    911                 Exceptions.LIST_Error, "get-static-long");
    912 
    913     /** {@code r: float; f: static field spec of type float :: r = f} */
    914     public static final Rop GET_STATIC_FLOAT =
    915         new Rop(RegOps.GET_STATIC, Type.FLOAT, StdTypeList.EMPTY,
    916                 Exceptions.LIST_Error, "get-static-float");
    917 
    918     /** {@code r: double; f: static field spec of type double :: r = f} */
    919     public static final Rop GET_STATIC_DOUBLE =
    920         new Rop(RegOps.GET_STATIC, Type.DOUBLE, StdTypeList.EMPTY,
    921                 Exceptions.LIST_Error, "get-static-double");
    922 
    923     /** {@code r: Object; f: static field spec of type Object :: r = f} */
    924     public static final Rop GET_STATIC_OBJECT =
    925         new Rop(RegOps.GET_STATIC, Type.OBJECT, StdTypeList.EMPTY,
    926                 Exceptions.LIST_Error, "get-static-object");
    927 
    928     /** {@code r: boolean; f: static field spec of type boolean :: r = f} */
    929     public static final Rop GET_STATIC_BOOLEAN =
    930         new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY,
    931                 Exceptions.LIST_Error, "get-field-boolean");
    932 
    933     /** {@code r: byte; f: static field spec of type byte :: r = f} */
    934     public static final Rop GET_STATIC_BYTE =
    935         new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY,
    936                 Exceptions.LIST_Error, "get-field-byte");
    937 
    938     /** {@code r: char; f: static field spec of type char :: r = f} */
    939     public static final Rop GET_STATIC_CHAR =
    940         new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY,
    941                 Exceptions.LIST_Error, "get-field-char");
    942 
    943     /** {@code r: short; f: static field spec of type short :: r = f} */
    944     public static final Rop GET_STATIC_SHORT =
    945         new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY,
    946                 Exceptions.LIST_Error, "get-field-short");
    947 
    948     /**
    949      * {@code x: int; y: Object; f: instance field spec of type
    950      * int :: y.f = x}
    951      */
    952     public static final Rop PUT_FIELD_INT =
    953         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT,
    954                 Exceptions.LIST_Error_NullPointerException, "put-field-int");
    955 
    956     /**
    957      * {@code x: long; y: Object; f: instance field spec of type
    958      * long :: y.f = x}
    959      */
    960     public static final Rop PUT_FIELD_LONG =
    961         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.LONG_OBJECT,
    962                 Exceptions.LIST_Error_NullPointerException, "put-field-long");
    963 
    964     /**
    965      * {@code x: float; y: Object; f: instance field spec of type
    966      * float :: y.f = x}
    967      */
    968     public static final Rop PUT_FIELD_FLOAT =
    969         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.FLOAT_OBJECT,
    970                 Exceptions.LIST_Error_NullPointerException,
    971                 "put-field-float");
    972 
    973     /**
    974      * {@code x: double; y: Object; f: instance field spec of type
    975      * double :: y.f = x}
    976      */
    977     public static final Rop PUT_FIELD_DOUBLE =
    978         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.DOUBLE_OBJECT,
    979                 Exceptions.LIST_Error_NullPointerException,
    980                 "put-field-double");
    981 
    982     /**
    983      * {@code x: Object; y: Object; f: instance field spec of type
    984      * Object :: y.f = x}
    985      */
    986     public static final Rop PUT_FIELD_OBJECT =
    987         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.OBJECT_OBJECT,
    988                 Exceptions.LIST_Error_NullPointerException,
    989                 "put-field-object");
    990 
    991     /**
    992      * {@code x: int; y: Object; f: instance field spec of type
    993      * boolean :: y.f = x}
    994      */
    995     public static final Rop PUT_FIELD_BOOLEAN =
    996         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT,
    997                 Exceptions.LIST_Error_NullPointerException,
    998                 "put-field-boolean");
    999 
   1000     /**
   1001      * {@code x: int; y: Object; f: instance field spec of type
   1002      * byte :: y.f = x}
   1003      */
   1004     public static final Rop PUT_FIELD_BYTE =
   1005         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT,
   1006                 Exceptions.LIST_Error_NullPointerException,
   1007                 "put-field-byte");
   1008 
   1009     /**
   1010      * {@code x: int; y: Object; f: instance field spec of type
   1011      * char :: y.f = x}
   1012      */
   1013     public static final Rop PUT_FIELD_CHAR =
   1014         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT,
   1015                 Exceptions.LIST_Error_NullPointerException,
   1016                 "put-field-char");
   1017 
   1018     /**
   1019      * {@code x: int; y: Object; f: instance field spec of type
   1020      * short :: y.f = x}
   1021      */
   1022     public static final Rop PUT_FIELD_SHORT =
   1023         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT,
   1024                 Exceptions.LIST_Error_NullPointerException,
   1025                 "put-field-short");
   1026 
   1027     /** {@code f: static field spec of type int; x: int :: f = x} */
   1028     public static final Rop PUT_STATIC_INT =
   1029         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT,
   1030                 Exceptions.LIST_Error, "put-static-int");
   1031 
   1032     /** {@code f: static field spec of type long; x: long :: f = x} */
   1033     public static final Rop PUT_STATIC_LONG =
   1034         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.LONG,
   1035                 Exceptions.LIST_Error, "put-static-long");
   1036 
   1037     /** {@code f: static field spec of type float; x: float :: f = x} */
   1038     public static final Rop PUT_STATIC_FLOAT =
   1039         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.FLOAT,
   1040                 Exceptions.LIST_Error, "put-static-float");
   1041 
   1042     /** {@code f: static field spec of type double; x: double :: f = x} */
   1043     public static final Rop PUT_STATIC_DOUBLE =
   1044         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.DOUBLE,
   1045                 Exceptions.LIST_Error, "put-static-double");
   1046 
   1047     /** {@code f: static field spec of type Object; x: Object :: f = x} */
   1048     public static final Rop PUT_STATIC_OBJECT =
   1049         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.OBJECT,
   1050                 Exceptions.LIST_Error, "put-static-object");
   1051 
   1052     /**
   1053      * {@code f: static field spec of type boolean; x: boolean :: f =
   1054      * x}
   1055      */
   1056     public static final Rop PUT_STATIC_BOOLEAN =
   1057         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT,
   1058                 Exceptions.LIST_Error, "put-static-boolean");
   1059 
   1060     /** {@code f: static field spec of type byte; x: byte :: f = x} */
   1061     public static final Rop PUT_STATIC_BYTE =
   1062         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT,
   1063                 Exceptions.LIST_Error, "put-static-byte");
   1064 
   1065     /** {@code f: static field spec of type char; x: char :: f = x} */
   1066     public static final Rop PUT_STATIC_CHAR =
   1067         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT,
   1068                 Exceptions.LIST_Error, "put-static-char");
   1069 
   1070     /** {@code f: static field spec of type short; x: short :: f = x} */
   1071     public static final Rop PUT_STATIC_SHORT =
   1072         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT,
   1073                 Exceptions.LIST_Error, "put-static-short");
   1074 
   1075     /** {@code x: Int :: local variable begins in x} */
   1076     public static final Rop MARK_LOCAL_INT =
   1077             new Rop (RegOps.MARK_LOCAL, Type.VOID,
   1078                     StdTypeList.INT, "mark-local-int");
   1079 
   1080     /** {@code x: Long :: local variable begins in x} */
   1081     public static final Rop MARK_LOCAL_LONG =
   1082             new Rop (RegOps.MARK_LOCAL, Type.VOID,
   1083                     StdTypeList.LONG, "mark-local-long");
   1084 
   1085     /** {@code x: Float :: local variable begins in x} */
   1086     public static final Rop MARK_LOCAL_FLOAT =
   1087             new Rop (RegOps.MARK_LOCAL, Type.VOID,
   1088                     StdTypeList.FLOAT, "mark-local-float");
   1089 
   1090     /** {@code x: Double :: local variable begins in x} */
   1091     public static final Rop MARK_LOCAL_DOUBLE =
   1092             new Rop (RegOps.MARK_LOCAL, Type.VOID,
   1093                     StdTypeList.DOUBLE, "mark-local-double");
   1094 
   1095     /** {@code x: Object :: local variable begins in x} */
   1096     public static final Rop MARK_LOCAL_OBJECT =
   1097             new Rop (RegOps.MARK_LOCAL, Type.VOID,
   1098                     StdTypeList.OBJECT, "mark-local-object");
   1099 
   1100     /** {@code T: Any primitive type; v0..vx: T :: {v0, ..., vx}} */
   1101     public static final Rop FILL_ARRAY_DATA =
   1102         new Rop(RegOps.FILL_ARRAY_DATA, Type.VOID, StdTypeList.EMPTY,
   1103                 "fill-array-data");
   1104 
   1105     /**
   1106      * Returns the appropriate rop for the given opcode, destination,
   1107      * and sources. The result is typically, but not necessarily, a
   1108      * shared instance.
   1109      *
   1110      * <p><b>Note:</b> This method does not do complete error checking on
   1111      * its arguments, and so it may return an instance which seemed "right
   1112      * enough" even though in actuality the passed arguments don't quite
   1113      * match what is returned. TODO: Revisit this issue.</p>
   1114      *
   1115      * @param opcode the opcode
   1116      * @param dest {@code non-null;} destination (result) type, or
   1117      * {@link Type#VOID} if none
   1118      * @param sources {@code non-null;} list of source types
   1119      * @param cst {@code null-ok;} associated constant, if any
   1120      * @return {@code non-null;} an appropriate instance
   1121      */
   1122     public static Rop ropFor(int opcode, TypeBearer dest, TypeList sources,
   1123             Constant cst) {
   1124         switch (opcode) {
   1125             case RegOps.NOP: return NOP;
   1126             case RegOps.MOVE: return opMove(dest);
   1127             case RegOps.MOVE_PARAM: return opMoveParam(dest);
   1128             case RegOps.MOVE_EXCEPTION: return opMoveException(dest);
   1129             case RegOps.CONST: return opConst(dest);
   1130             case RegOps.GOTO: return GOTO;
   1131             case RegOps.IF_EQ: return opIfEq(sources);
   1132             case RegOps.IF_NE: return opIfNe(sources);
   1133             case RegOps.IF_LT: return opIfLt(sources);
   1134             case RegOps.IF_GE: return opIfGe(sources);
   1135             case RegOps.IF_LE: return opIfLe(sources);
   1136             case RegOps.IF_GT: return opIfGt(sources);
   1137             case RegOps.SWITCH: return SWITCH;
   1138             case RegOps.ADD: return opAdd(sources);
   1139             case RegOps.SUB: return opSub(sources);
   1140             case RegOps.MUL: return opMul(sources);
   1141             case RegOps.DIV: return opDiv(sources);
   1142             case RegOps.REM: return opRem(sources);
   1143             case RegOps.NEG: return opNeg(dest);
   1144             case RegOps.AND: return opAnd(sources);
   1145             case RegOps.OR: return opOr(sources);
   1146             case RegOps.XOR: return opXor(sources);
   1147             case RegOps.SHL: return opShl(sources);
   1148             case RegOps.SHR: return opShr(sources);
   1149             case RegOps.USHR: return opUshr(sources);
   1150             case RegOps.NOT: return opNot(dest);
   1151             case RegOps.CMPL: return opCmpl(sources.getType(0));
   1152             case RegOps.CMPG: return opCmpg(sources.getType(0));
   1153             case RegOps.CONV: return opConv(dest, sources.getType(0));
   1154             case RegOps.TO_BYTE: return TO_BYTE;
   1155             case RegOps.TO_CHAR: return TO_CHAR;
   1156             case RegOps.TO_SHORT: return TO_SHORT;
   1157             case RegOps.RETURN: {
   1158                 if (sources.size() == 0) {
   1159                     return RETURN_VOID;
   1160                 }
   1161                 return opReturn(sources.getType(0));
   1162             }
   1163             case RegOps.ARRAY_LENGTH: return ARRAY_LENGTH;
   1164             case RegOps.THROW: return THROW;
   1165             case RegOps.MONITOR_ENTER: return MONITOR_ENTER;
   1166             case RegOps.MONITOR_EXIT: return MONITOR_EXIT;
   1167             case RegOps.AGET: {
   1168                 Type source = sources.getType(0);
   1169                 Type componentType;
   1170                 if (source == Type.KNOWN_NULL) {
   1171                     /*
   1172                      * Treat a known-null as an array of the expected
   1173                      * result type.
   1174                      */
   1175                     componentType = dest.getType();
   1176                 } else {
   1177                     componentType = source.getComponentType();
   1178                 }
   1179                 return opAget(componentType);
   1180             }
   1181             case RegOps.APUT: {
   1182                 Type source = sources.getType(1);
   1183                 Type componentType;
   1184                 if (source == Type.KNOWN_NULL) {
   1185                     /*
   1186                      * Treat a known-null as an array of the type being
   1187                      * stored.
   1188                      */
   1189                     componentType = sources.getType(0);
   1190                 } else {
   1191                     componentType = source.getComponentType();
   1192                 }
   1193                 return opAput(componentType);
   1194             }
   1195             case RegOps.NEW_INSTANCE: return NEW_INSTANCE;
   1196             case RegOps.NEW_ARRAY: return opNewArray(dest.getType());
   1197             case RegOps.CHECK_CAST: return CHECK_CAST;
   1198             case RegOps.INSTANCE_OF: return INSTANCE_OF;
   1199             case RegOps.GET_FIELD: return opGetField(dest);
   1200             case RegOps.GET_STATIC: return opGetStatic(dest);
   1201             case RegOps.PUT_FIELD: return opPutField(sources.getType(0));
   1202             case RegOps.PUT_STATIC: return opPutStatic(sources.getType(0));
   1203             case RegOps.INVOKE_STATIC: {
   1204                 return opInvokeStatic(((CstMethodRef) cst).getPrototype());
   1205             }
   1206             case RegOps.INVOKE_VIRTUAL: {
   1207                 CstBaseMethodRef cstMeth = (CstMethodRef) cst;
   1208                 Prototype meth = cstMeth.getPrototype();
   1209                 CstType definer = cstMeth.getDefiningClass();
   1210                 meth = meth.withFirstParameter(definer.getClassType());
   1211                 return opInvokeVirtual(meth);
   1212             }
   1213             case RegOps.INVOKE_SUPER: {
   1214                 CstBaseMethodRef cstMeth = (CstMethodRef) cst;
   1215                 Prototype meth = cstMeth.getPrototype();
   1216                 CstType definer = cstMeth.getDefiningClass();
   1217                 meth = meth.withFirstParameter(definer.getClassType());
   1218                 return opInvokeSuper(meth);
   1219             }
   1220             case RegOps.INVOKE_DIRECT: {
   1221                 CstBaseMethodRef cstMeth = (CstMethodRef) cst;
   1222                 Prototype meth = cstMeth.getPrototype();
   1223                 CstType definer = cstMeth.getDefiningClass();
   1224                 meth = meth.withFirstParameter(definer.getClassType());
   1225                 return opInvokeDirect(meth);
   1226             }
   1227             case RegOps.INVOKE_INTERFACE: {
   1228                 CstBaseMethodRef cstMeth = (CstMethodRef) cst;
   1229                 Prototype meth = cstMeth.getPrototype();
   1230                 CstType definer = cstMeth.getDefiningClass();
   1231                 meth = meth.withFirstParameter(definer.getClassType());
   1232                 return opInvokeInterface(meth);
   1233             }
   1234         }
   1235 
   1236         throw new RuntimeException("unknown opcode " + RegOps.opName(opcode));
   1237     }
   1238 
   1239     /**
   1240      * Returns the appropriate {@code move} rop for the given type. The
   1241      * result is a shared instance.
   1242      *
   1243      * @param type {@code non-null;} type of value being moved
   1244      * @return {@code non-null;} an appropriate instance
   1245      */
   1246     public static Rop opMove(TypeBearer type) {
   1247         switch (type.getBasicFrameType()) {
   1248             case Type.BT_INT:    return MOVE_INT;
   1249             case Type.BT_LONG:   return MOVE_LONG;
   1250             case Type.BT_FLOAT:  return MOVE_FLOAT;
   1251             case Type.BT_DOUBLE: return MOVE_DOUBLE;
   1252             case Type.BT_OBJECT: return MOVE_OBJECT;
   1253             case Type.BT_ADDR:   return MOVE_RETURN_ADDRESS;
   1254         }
   1255 
   1256         return throwBadType(type);
   1257     }
   1258 
   1259     /**
   1260      * Returns the appropriate {@code move-param} rop for the
   1261      * given type. The result is a shared instance.
   1262      *
   1263      * @param type {@code non-null;} type of value being moved
   1264      * @return {@code non-null;} an appropriate instance
   1265      */
   1266     public static Rop opMoveParam(TypeBearer type) {
   1267         switch (type.getBasicFrameType()) {
   1268             case Type.BT_INT:    return MOVE_PARAM_INT;
   1269             case Type.BT_LONG:   return MOVE_PARAM_LONG;
   1270             case Type.BT_FLOAT:  return MOVE_PARAM_FLOAT;
   1271             case Type.BT_DOUBLE: return MOVE_PARAM_DOUBLE;
   1272             case Type.BT_OBJECT: return MOVE_PARAM_OBJECT;
   1273         }
   1274 
   1275         return throwBadType(type);
   1276     }
   1277 
   1278     /**
   1279      * Returns the appropriate {@code move-exception} rop for the
   1280      * given type. The result may be a shared instance.
   1281      *
   1282      * @param type {@code non-null;} type of the exception
   1283      * @return {@code non-null;} an appropriate instance
   1284      */
   1285     public static Rop opMoveException(TypeBearer type) {
   1286         return new Rop(RegOps.MOVE_EXCEPTION, type.getType(),
   1287                        StdTypeList.EMPTY, (String) null);
   1288     }
   1289 
   1290     /**
   1291      * Returns the appropriate {@code move-result} rop for the
   1292      * given type. The result may be a shared instance.
   1293      *
   1294      * @param type {@code non-null;} type of the parameter
   1295      * @return {@code non-null;} an appropriate instance
   1296      */
   1297     public static Rop opMoveResult(TypeBearer type) {
   1298         return new Rop(RegOps.MOVE_RESULT, type.getType(),
   1299                        StdTypeList.EMPTY, (String) null);
   1300     }
   1301 
   1302     /**
   1303      * Returns the appropriate {@code move-result-pseudo} rop for the
   1304      * given type. The result may be a shared instance.
   1305      *
   1306      * @param type {@code non-null;} type of the parameter
   1307      * @return {@code non-null;} an appropriate instance
   1308      */
   1309     public static Rop opMoveResultPseudo(TypeBearer type) {
   1310         return new Rop(RegOps.MOVE_RESULT_PSEUDO, type.getType(),
   1311                        StdTypeList.EMPTY, (String) null);
   1312     }
   1313 
   1314     /**
   1315      * Returns the appropriate {@code const} rop for the given
   1316      * type. The result is a shared instance.
   1317      *
   1318      * @param type {@code non-null;} type of the constant
   1319      * @return {@code non-null;} an appropriate instance
   1320      */
   1321     public static Rop opConst(TypeBearer type) {
   1322         if (type.getType() == Type.KNOWN_NULL) {
   1323             return CONST_OBJECT_NOTHROW;
   1324         }
   1325 
   1326         switch (type.getBasicFrameType()) {
   1327             case Type.BT_INT:    return CONST_INT;
   1328             case Type.BT_LONG:   return CONST_LONG;
   1329             case Type.BT_FLOAT:  return CONST_FLOAT;
   1330             case Type.BT_DOUBLE: return CONST_DOUBLE;
   1331             case Type.BT_OBJECT: return CONST_OBJECT;
   1332         }
   1333 
   1334         return throwBadType(type);
   1335     }
   1336 
   1337     /**
   1338      * Returns the appropriate {@code if-eq} rop for the given
   1339      * sources. The result is a shared instance.
   1340      *
   1341      * @param types {@code non-null;} source types
   1342      * @return {@code non-null;} an appropriate instance
   1343      */
   1344     public static Rop opIfEq(TypeList types) {
   1345         return pickIf(types, IF_EQZ_INT, IF_EQZ_OBJECT,
   1346                       IF_EQ_INT, IF_EQ_OBJECT);
   1347     }
   1348 
   1349     /**
   1350      * Returns the appropriate {@code if-ne} rop for the given
   1351      * sources. The result is a shared instance.
   1352      *
   1353      * @param types {@code non-null;} source types
   1354      * @return {@code non-null;} an appropriate instance
   1355      */
   1356     public static Rop opIfNe(TypeList types) {
   1357         return pickIf(types, IF_NEZ_INT, IF_NEZ_OBJECT,
   1358                       IF_NE_INT, IF_NE_OBJECT);
   1359     }
   1360 
   1361     /**
   1362      * Returns the appropriate {@code if-lt} rop for the given
   1363      * sources. The result is a shared instance.
   1364      *
   1365      * @param types {@code non-null;} source types
   1366      * @return {@code non-null;} an appropriate instance
   1367      */
   1368     public static Rop opIfLt(TypeList types) {
   1369         return pickIf(types, IF_LTZ_INT, null, IF_LT_INT, null);
   1370     }
   1371 
   1372     /**
   1373      * Returns the appropriate {@code if-ge} rop for the given
   1374      * sources. The result is a shared instance.
   1375      *
   1376      * @param types {@code non-null;} source types
   1377      * @return {@code non-null;} an appropriate instance
   1378      */
   1379     public static Rop opIfGe(TypeList types) {
   1380         return pickIf(types, IF_GEZ_INT, null, IF_GE_INT, null);
   1381     }
   1382 
   1383     /**
   1384      * Returns the appropriate {@code if-gt} rop for the given
   1385      * sources. The result is a shared instance.
   1386      *
   1387      * @param types {@code non-null;} source types
   1388      * @return {@code non-null;} an appropriate instance
   1389      */
   1390     public static Rop opIfGt(TypeList types) {
   1391         return pickIf(types, IF_GTZ_INT, null, IF_GT_INT, null);
   1392     }
   1393 
   1394     /**
   1395      * Returns the appropriate {@code if-le} rop for the given
   1396      * sources. The result is a shared instance.
   1397      *
   1398      * @param types {@code non-null;} source types
   1399      * @return {@code non-null;} an appropriate instance
   1400      */
   1401     public static Rop opIfLe(TypeList types) {
   1402         return pickIf(types, IF_LEZ_INT, null, IF_LE_INT, null);
   1403     }
   1404 
   1405     /**
   1406      * Helper for all the {@code if*}-related methods, which
   1407      * checks types and picks one of the four variants, throwing if
   1408      * there's a problem.
   1409      *
   1410      * @param types {@code non-null;} the types
   1411      * @param intZ {@code non-null;} the int-to-0 comparison
   1412      * @param objZ {@code null-ok;} the object-to-null comparison
   1413      * @param intInt {@code non-null;} the int-to-int comparison
   1414      * @param objObj {@code non-null;} the object-to-object comparison
   1415      * @return {@code non-null;} the appropriate instance
   1416      */
   1417     private static Rop pickIf(TypeList types, Rop intZ, Rop objZ, Rop intInt,
   1418                               Rop objObj) {
   1419         switch(types.size()) {
   1420             case 1: {
   1421                 switch (types.getType(0).getBasicFrameType()) {
   1422                     case Type.BT_INT: {
   1423                         return intZ;
   1424                     }
   1425                     case Type.BT_OBJECT: {
   1426                         if (objZ != null) {
   1427                             return objZ;
   1428                         }
   1429                     }
   1430                 }
   1431                 break;
   1432             }
   1433             case 2: {
   1434                 int bt = types.getType(0).getBasicFrameType();
   1435                 if (bt == types.getType(1).getBasicFrameType()) {
   1436                     switch (bt) {
   1437                         case Type.BT_INT: {
   1438                             return intInt;
   1439                         }
   1440                         case Type.BT_OBJECT: {
   1441                             if (objObj != null) {
   1442                                 return objObj;
   1443                             }
   1444                         }
   1445                     }
   1446                 }
   1447                 break;
   1448             }
   1449         }
   1450 
   1451         return throwBadTypes(types);
   1452     }
   1453 
   1454     /**
   1455      * Returns the appropriate {@code add} rop for the given
   1456      * types. The result is a shared instance.
   1457      *
   1458      * @param types {@code non-null;} types of the sources
   1459      * @return {@code non-null;} an appropriate instance
   1460      */
   1461     public static Rop opAdd(TypeList types) {
   1462         return pickBinaryOp(types, ADD_CONST_INT, ADD_CONST_LONG,
   1463                             ADD_CONST_FLOAT, ADD_CONST_DOUBLE, ADD_INT,
   1464                             ADD_LONG, ADD_FLOAT, ADD_DOUBLE);
   1465     }
   1466 
   1467     /**
   1468      * Returns the appropriate {@code sub} rop for the given
   1469      * types. The result is a shared instance.
   1470      *
   1471      * @param types {@code non-null;} types of the sources
   1472      * @return {@code non-null;} an appropriate instance
   1473      */
   1474     public static Rop opSub(TypeList types) {
   1475         return pickBinaryOp(types, SUB_CONST_INT, SUB_CONST_LONG,
   1476                             SUB_CONST_FLOAT, SUB_CONST_DOUBLE, SUB_INT,
   1477                             SUB_LONG, SUB_FLOAT, SUB_DOUBLE);
   1478     }
   1479 
   1480     /**
   1481      * Returns the appropriate {@code mul} rop for the given
   1482      * types. The result is a shared instance.
   1483      *
   1484      * @param types {@code non-null;} types of the sources
   1485      * @return {@code non-null;} an appropriate instance
   1486      */
   1487     public static Rop opMul(TypeList types) {
   1488         return pickBinaryOp(types, MUL_CONST_INT, MUL_CONST_LONG,
   1489                             MUL_CONST_FLOAT, MUL_CONST_DOUBLE, MUL_INT,
   1490                             MUL_LONG, MUL_FLOAT, MUL_DOUBLE);
   1491     }
   1492 
   1493     /**
   1494      * Returns the appropriate {@code div} rop for the given
   1495      * types. The result is a shared instance.
   1496      *
   1497      * @param types {@code non-null;} types of the sources
   1498      * @return {@code non-null;} an appropriate instance
   1499      */
   1500     public static Rop opDiv(TypeList types) {
   1501         return pickBinaryOp(types, DIV_CONST_INT, DIV_CONST_LONG,
   1502                             DIV_CONST_FLOAT, DIV_CONST_DOUBLE, DIV_INT,
   1503                             DIV_LONG, DIV_FLOAT, DIV_DOUBLE);
   1504     }
   1505 
   1506     /**
   1507      * Returns the appropriate {@code rem} rop for the given
   1508      * types. The result is a shared instance.
   1509      *
   1510      * @param types {@code non-null;} types of the sources
   1511      * @return {@code non-null;} an appropriate instance
   1512      */
   1513     public static Rop opRem(TypeList types) {
   1514         return pickBinaryOp(types, REM_CONST_INT, REM_CONST_LONG,
   1515                             REM_CONST_FLOAT, REM_CONST_DOUBLE, REM_INT,
   1516                             REM_LONG, REM_FLOAT, REM_DOUBLE);
   1517     }
   1518 
   1519     /**
   1520      * Returns the appropriate {@code and} rop for the given
   1521      * types. The result is a shared instance.
   1522      *
   1523      * @param types {@code non-null;} types of the sources
   1524      * @return {@code non-null;} an appropriate instance
   1525      */
   1526     public static Rop opAnd(TypeList types) {
   1527         return pickBinaryOp(types, AND_CONST_INT, AND_CONST_LONG, null, null,
   1528                             AND_INT, AND_LONG, null, null);
   1529     }
   1530 
   1531     /**
   1532      * Returns the appropriate {@code or} rop for the given
   1533      * types. The result is a shared instance.
   1534      *
   1535      * @param types {@code non-null;} types of the sources
   1536      * @return {@code non-null;} an appropriate instance
   1537      */
   1538     public static Rop opOr(TypeList types) {
   1539         return pickBinaryOp(types, OR_CONST_INT, OR_CONST_LONG, null, null,
   1540                             OR_INT, OR_LONG, null, null);
   1541     }
   1542 
   1543     /**
   1544      * Returns the appropriate {@code xor} rop for the given
   1545      * types. The result is a shared instance.
   1546      *
   1547      * @param types {@code non-null;} types of the sources
   1548      * @return {@code non-null;} an appropriate instance
   1549      */
   1550     public static Rop opXor(TypeList types) {
   1551         return pickBinaryOp(types, XOR_CONST_INT, XOR_CONST_LONG, null, null,
   1552                             XOR_INT, XOR_LONG, null, null);
   1553     }
   1554 
   1555     /**
   1556      * Returns the appropriate {@code shl} rop for the given
   1557      * types. The result is a shared instance.
   1558      *
   1559      * @param types {@code non-null;} types of the sources
   1560      * @return {@code non-null;} an appropriate instance
   1561      */
   1562     public static Rop opShl(TypeList types) {
   1563         return pickBinaryOp(types, SHL_CONST_INT, SHL_CONST_LONG, null, null,
   1564                             SHL_INT, SHL_LONG, null, null);
   1565     }
   1566 
   1567     /**
   1568      * Returns the appropriate {@code shr} rop for the given
   1569      * types. The result is a shared instance.
   1570      *
   1571      * @param types {@code non-null;} types of the sources
   1572      * @return {@code non-null;} an appropriate instance
   1573      */
   1574     public static Rop opShr(TypeList types) {
   1575         return pickBinaryOp(types, SHR_CONST_INT, SHR_CONST_LONG, null, null,
   1576                             SHR_INT, SHR_LONG, null, null);
   1577     }
   1578 
   1579     /**
   1580      * Returns the appropriate {@code ushr} rop for the given
   1581      * types. The result is a shared instance.
   1582      *
   1583      * @param types {@code non-null;} types of the sources
   1584      * @return {@code non-null;} an appropriate instance
   1585      */
   1586     public static Rop opUshr(TypeList types) {
   1587         return pickBinaryOp(types, USHR_CONST_INT, USHR_CONST_LONG, null, null,
   1588                             USHR_INT, USHR_LONG, null, null);
   1589     }
   1590 
   1591     /**
   1592      * Returns the appropriate binary arithmetic rop for the given type
   1593      * and arguments. The result is a shared instance.
   1594      *
   1595      * @param types {@code non-null;} sources of the operation
   1596      * @param int1 {@code non-null;} the int-to-constant rop
   1597      * @param long1 {@code non-null;} the long-to-constant rop
   1598      * @param float1 {@code null-ok;} the float-to-constant rop, if any
   1599      * @param double1 {@code null-ok;} the double-to-constant rop, if any
   1600      * @param int2 {@code non-null;} the int-to-int rop
   1601      * @param long2 {@code non-null;} the long-to-long or long-to-int rop
   1602      * @param float2 {@code null-ok;} the float-to-float rop, if any
   1603      * @param double2 {@code null-ok;} the double-to-double rop, if any
   1604      * @return {@code non-null;} an appropriate instance
   1605      */
   1606     private static Rop pickBinaryOp(TypeList types, Rop int1, Rop long1,
   1607                                     Rop float1, Rop double1, Rop int2,
   1608                                     Rop long2, Rop float2, Rop double2) {
   1609         int bt1 = types.getType(0).getBasicFrameType();
   1610         Rop result = null;
   1611 
   1612         switch (types.size()) {
   1613             case 1: {
   1614                 switch(bt1) {
   1615                     case Type.BT_INT:    return int1;
   1616                     case Type.BT_LONG:   return long1;
   1617                     case Type.BT_FLOAT:  result = float1; break;
   1618                     case Type.BT_DOUBLE: result = double1; break;
   1619                 }
   1620                 break;
   1621             }
   1622             case 2: {
   1623                 switch(bt1) {
   1624                     case Type.BT_INT:    return int2;
   1625                     case Type.BT_LONG:   return long2;
   1626                     case Type.BT_FLOAT:  result = float2; break;
   1627                     case Type.BT_DOUBLE: result = double2; break;
   1628                 }
   1629                 break;
   1630             }
   1631         }
   1632 
   1633         if (result == null) {
   1634             return throwBadTypes(types);
   1635         }
   1636 
   1637         return result;
   1638     }
   1639 
   1640     /**
   1641      * Returns the appropriate {@code neg} rop for the given type. The
   1642      * result is a shared instance.
   1643      *
   1644      * @param type {@code non-null;} type of value being operated on
   1645      * @return {@code non-null;} an appropriate instance
   1646      */
   1647     public static Rop opNeg(TypeBearer type) {
   1648         switch (type.getBasicFrameType()) {
   1649             case Type.BT_INT:    return NEG_INT;
   1650             case Type.BT_LONG:   return NEG_LONG;
   1651             case Type.BT_FLOAT:  return NEG_FLOAT;
   1652             case Type.BT_DOUBLE: return NEG_DOUBLE;
   1653         }
   1654 
   1655         return throwBadType(type);
   1656     }
   1657 
   1658     /**
   1659      * Returns the appropriate {@code not} rop for the given type. The
   1660      * result is a shared instance.
   1661      *
   1662      * @param type {@code non-null;} type of value being operated on
   1663      * @return {@code non-null;} an appropriate instance
   1664      */
   1665     public static Rop opNot(TypeBearer type) {
   1666         switch (type.getBasicFrameType()) {
   1667             case Type.BT_INT:  return NOT_INT;
   1668             case Type.BT_LONG: return NOT_LONG;
   1669         }
   1670 
   1671         return throwBadType(type);
   1672     }
   1673 
   1674     /**
   1675      * Returns the appropriate {@code cmpl} rop for the given type. The
   1676      * result is a shared instance.
   1677      *
   1678      * @param type {@code non-null;} type of value being compared
   1679      * @return {@code non-null;} an appropriate instance
   1680      */
   1681     public static Rop opCmpl(TypeBearer type) {
   1682         switch (type.getBasicType()) {
   1683             case Type.BT_LONG:   return CMPL_LONG;
   1684             case Type.BT_FLOAT:  return CMPL_FLOAT;
   1685             case Type.BT_DOUBLE: return CMPL_DOUBLE;
   1686         }
   1687 
   1688         return throwBadType(type);
   1689     }
   1690 
   1691     /**
   1692      * Returns the appropriate {@code cmpg} rop for the given type. The
   1693      * result is a shared instance.
   1694      *
   1695      * @param type {@code non-null;} type of value being compared
   1696      * @return {@code non-null;} an appropriate instance
   1697      */
   1698     public static Rop opCmpg(TypeBearer type) {
   1699         switch (type.getBasicType()) {
   1700             case Type.BT_FLOAT:  return CMPG_FLOAT;
   1701             case Type.BT_DOUBLE: return CMPG_DOUBLE;
   1702         }
   1703 
   1704         return throwBadType(type);
   1705     }
   1706 
   1707     /**
   1708      * Returns the appropriate {@code conv} rop for the given types. The
   1709      * result is a shared instance.
   1710      *
   1711      * @param dest {@code non-null;} target value type
   1712      * @param source {@code non-null;} source value type
   1713      * @return {@code non-null;} an appropriate instance
   1714      */
   1715     public static Rop opConv(TypeBearer dest, TypeBearer source) {
   1716         int dbt = dest.getBasicFrameType();
   1717         switch (source.getBasicFrameType()) {
   1718             case Type.BT_INT: {
   1719                 switch (dbt) {
   1720                     case Type.BT_LONG:   return CONV_I2L;
   1721                     case Type.BT_FLOAT:  return CONV_I2F;
   1722                     case Type.BT_DOUBLE: return CONV_I2D;
   1723                 }
   1724             }
   1725             case Type.BT_LONG: {
   1726                 switch (dbt) {
   1727                     case Type.BT_INT:    return CONV_L2I;
   1728                     case Type.BT_FLOAT:  return CONV_L2F;
   1729                     case Type.BT_DOUBLE: return CONV_L2D;
   1730                 }
   1731             }
   1732             case Type.BT_FLOAT: {
   1733                 switch (dbt) {
   1734                     case Type.BT_INT:    return CONV_F2I;
   1735                     case Type.BT_LONG:   return CONV_F2L;
   1736                     case Type.BT_DOUBLE: return CONV_F2D;
   1737                 }
   1738             }
   1739             case Type.BT_DOUBLE: {
   1740                 switch (dbt) {
   1741                     case Type.BT_INT:   return CONV_D2I;
   1742                     case Type.BT_LONG:  return CONV_D2L;
   1743                     case Type.BT_FLOAT: return CONV_D2F;
   1744                 }
   1745             }
   1746         }
   1747 
   1748         return throwBadTypes(StdTypeList.make(dest.getType(),
   1749                                               source.getType()));
   1750     }
   1751 
   1752     /**
   1753      * Returns the appropriate {@code return} rop for the given type. The
   1754      * result is a shared instance.
   1755      *
   1756      * @param type {@code non-null;} type of value being returned
   1757      * @return {@code non-null;} an appropriate instance
   1758      */
   1759     public static Rop opReturn(TypeBearer type) {
   1760         switch (type.getBasicFrameType()) {
   1761             case Type.BT_INT:    return RETURN_INT;
   1762             case Type.BT_LONG:   return RETURN_LONG;
   1763             case Type.BT_FLOAT:  return RETURN_FLOAT;
   1764             case Type.BT_DOUBLE: return RETURN_DOUBLE;
   1765             case Type.BT_OBJECT: return RETURN_OBJECT;
   1766             case Type.BT_VOID:   return RETURN_VOID;
   1767         }
   1768 
   1769         return throwBadType(type);
   1770     }
   1771 
   1772     /**
   1773      * Returns the appropriate {@code aget} rop for the given type. The
   1774      * result is a shared instance.
   1775      *
   1776      * @param type {@code non-null;} element type of array being accessed
   1777      * @return {@code non-null;} an appropriate instance
   1778      */
   1779     public static Rop opAget(TypeBearer type) {
   1780         switch (type.getBasicType()) {
   1781             case Type.BT_INT:     return AGET_INT;
   1782             case Type.BT_LONG:    return AGET_LONG;
   1783             case Type.BT_FLOAT:   return AGET_FLOAT;
   1784             case Type.BT_DOUBLE:  return AGET_DOUBLE;
   1785             case Type.BT_OBJECT:  return AGET_OBJECT;
   1786             case Type.BT_BOOLEAN: return AGET_BOOLEAN;
   1787             case Type.BT_BYTE:    return AGET_BYTE;
   1788             case Type.BT_CHAR:    return AGET_CHAR;
   1789             case Type.BT_SHORT:   return AGET_SHORT;
   1790         }
   1791 
   1792         return throwBadType(type);
   1793     }
   1794 
   1795     /**
   1796      * Returns the appropriate {@code aput} rop for the given type. The
   1797      * result is a shared instance.
   1798      *
   1799      * @param type {@code non-null;} element type of array being accessed
   1800      * @return {@code non-null;} an appropriate instance
   1801      */
   1802     public static Rop opAput(TypeBearer type) {
   1803         switch (type.getBasicType()) {
   1804             case Type.BT_INT:     return APUT_INT;
   1805             case Type.BT_LONG:    return APUT_LONG;
   1806             case Type.BT_FLOAT:   return APUT_FLOAT;
   1807             case Type.BT_DOUBLE:  return APUT_DOUBLE;
   1808             case Type.BT_OBJECT:  return APUT_OBJECT;
   1809             case Type.BT_BOOLEAN: return APUT_BOOLEAN;
   1810             case Type.BT_BYTE:    return APUT_BYTE;
   1811             case Type.BT_CHAR:    return APUT_CHAR;
   1812             case Type.BT_SHORT:   return APUT_SHORT;
   1813         }
   1814 
   1815         return throwBadType(type);
   1816     }
   1817 
   1818     /**
   1819      * Returns the appropriate {@code new-array} rop for the given
   1820      * type. The result is a shared instance.
   1821      *
   1822      * @param arrayType {@code non-null;} array type of array being created
   1823      * @return {@code non-null;} an appropriate instance
   1824      */
   1825     public static Rop opNewArray(TypeBearer arrayType) {
   1826         Type type = arrayType.getType();
   1827         Type elementType = type.getComponentType();
   1828 
   1829         switch (elementType.getBasicType()) {
   1830             case Type.BT_INT:     return NEW_ARRAY_INT;
   1831             case Type.BT_LONG:    return NEW_ARRAY_LONG;
   1832             case Type.BT_FLOAT:   return NEW_ARRAY_FLOAT;
   1833             case Type.BT_DOUBLE:  return NEW_ARRAY_DOUBLE;
   1834             case Type.BT_BOOLEAN: return NEW_ARRAY_BOOLEAN;
   1835             case Type.BT_BYTE:    return NEW_ARRAY_BYTE;
   1836             case Type.BT_CHAR:    return NEW_ARRAY_CHAR;
   1837             case Type.BT_SHORT:   return NEW_ARRAY_SHORT;
   1838             case Type.BT_OBJECT: {
   1839                 return new Rop(RegOps.NEW_ARRAY, type, StdTypeList.INT,
   1840                         Exceptions.LIST_Error_NegativeArraySizeException,
   1841                         "new-array-object");
   1842             }
   1843         }
   1844 
   1845         return throwBadType(type);
   1846     }
   1847 
   1848     /**
   1849      * Returns the appropriate {@code filled-new-array} rop for the given
   1850      * type. The result may be a shared instance.
   1851      *
   1852      * @param arrayType {@code non-null;} type of array being created
   1853      * @param count {@code >= 0;} number of elements that the array should have
   1854      * @return {@code non-null;} an appropriate instance
   1855      */
   1856     public static Rop opFilledNewArray(TypeBearer arrayType, int count) {
   1857         Type type = arrayType.getType();
   1858         Type elementType = type.getComponentType();
   1859 
   1860         if (elementType.isCategory2()) {
   1861             return throwBadType(arrayType);
   1862         }
   1863 
   1864         if (count < 0) {
   1865             throw new IllegalArgumentException("count < 0");
   1866         }
   1867 
   1868         StdTypeList sourceTypes = new StdTypeList(count);
   1869 
   1870         for (int i = 0; i < count; i++) {
   1871             sourceTypes.set(i, elementType);
   1872         }
   1873 
   1874         // Note: The resulting rop is considered call-like.
   1875         return new Rop(RegOps.FILLED_NEW_ARRAY,
   1876                        sourceTypes,
   1877                        Exceptions.LIST_Error);
   1878     }
   1879 
   1880     /**
   1881      * Returns the appropriate {@code get-field} rop for the given
   1882      * type. The result is a shared instance.
   1883      *
   1884      * @param type {@code non-null;} type of the field in question
   1885      * @return {@code non-null;} an appropriate instance
   1886      */
   1887     public static Rop opGetField(TypeBearer type) {
   1888         switch (type.getBasicType()) {
   1889             case Type.BT_INT:     return GET_FIELD_INT;
   1890             case Type.BT_LONG:    return GET_FIELD_LONG;
   1891             case Type.BT_FLOAT:   return GET_FIELD_FLOAT;
   1892             case Type.BT_DOUBLE:  return GET_FIELD_DOUBLE;
   1893             case Type.BT_OBJECT:  return GET_FIELD_OBJECT;
   1894             case Type.BT_BOOLEAN: return GET_FIELD_BOOLEAN;
   1895             case Type.BT_BYTE:    return GET_FIELD_BYTE;
   1896             case Type.BT_CHAR:    return GET_FIELD_CHAR;
   1897             case Type.BT_SHORT:   return GET_FIELD_SHORT;
   1898         }
   1899 
   1900         return throwBadType(type);
   1901     }
   1902 
   1903     /**
   1904      * Returns the appropriate {@code put-field} rop for the given
   1905      * type. The result is a shared instance.
   1906      *
   1907      * @param type {@code non-null;} type of the field in question
   1908      * @return {@code non-null;} an appropriate instance
   1909      */
   1910     public static Rop opPutField(TypeBearer type) {
   1911         switch (type.getBasicType()) {
   1912             case Type.BT_INT:     return PUT_FIELD_INT;
   1913             case Type.BT_LONG:    return PUT_FIELD_LONG;
   1914             case Type.BT_FLOAT:   return PUT_FIELD_FLOAT;
   1915             case Type.BT_DOUBLE:  return PUT_FIELD_DOUBLE;
   1916             case Type.BT_OBJECT:  return PUT_FIELD_OBJECT;
   1917             case Type.BT_BOOLEAN: return PUT_FIELD_BOOLEAN;
   1918             case Type.BT_BYTE:    return PUT_FIELD_BYTE;
   1919             case Type.BT_CHAR:    return PUT_FIELD_CHAR;
   1920             case Type.BT_SHORT:   return PUT_FIELD_SHORT;
   1921         }
   1922 
   1923         return throwBadType(type);
   1924     }
   1925 
   1926     /**
   1927      * Returns the appropriate {@code get-static} rop for the given
   1928      * type. The result is a shared instance.
   1929      *
   1930      * @param type {@code non-null;} type of the field in question
   1931      * @return {@code non-null;} an appropriate instance
   1932      */
   1933     public static Rop opGetStatic(TypeBearer type) {
   1934         switch (type.getBasicType()) {
   1935             case Type.BT_INT:     return GET_STATIC_INT;
   1936             case Type.BT_LONG:    return GET_STATIC_LONG;
   1937             case Type.BT_FLOAT:   return GET_STATIC_FLOAT;
   1938             case Type.BT_DOUBLE:  return GET_STATIC_DOUBLE;
   1939             case Type.BT_OBJECT:  return GET_STATIC_OBJECT;
   1940             case Type.BT_BOOLEAN: return GET_STATIC_BOOLEAN;
   1941             case Type.BT_BYTE:    return GET_STATIC_BYTE;
   1942             case Type.BT_CHAR:    return GET_STATIC_CHAR;
   1943             case Type.BT_SHORT:   return GET_STATIC_SHORT;
   1944         }
   1945 
   1946         return throwBadType(type);
   1947     }
   1948 
   1949     /**
   1950      * Returns the appropriate {@code put-static} rop for the given
   1951      * type. The result is a shared instance.
   1952      *
   1953      * @param type {@code non-null;} type of the field in question
   1954      * @return {@code non-null;} an appropriate instance
   1955      */
   1956     public static Rop opPutStatic(TypeBearer type) {
   1957         switch (type.getBasicType()) {
   1958             case Type.BT_INT:     return PUT_STATIC_INT;
   1959             case Type.BT_LONG:    return PUT_STATIC_LONG;
   1960             case Type.BT_FLOAT:   return PUT_STATIC_FLOAT;
   1961             case Type.BT_DOUBLE:  return PUT_STATIC_DOUBLE;
   1962             case Type.BT_OBJECT:  return PUT_STATIC_OBJECT;
   1963             case Type.BT_BOOLEAN: return PUT_STATIC_BOOLEAN;
   1964             case Type.BT_BYTE:    return PUT_STATIC_BYTE;
   1965             case Type.BT_CHAR:    return PUT_STATIC_CHAR;
   1966             case Type.BT_SHORT:   return PUT_STATIC_SHORT;
   1967         }
   1968 
   1969         return throwBadType(type);
   1970     }
   1971 
   1972     /**
   1973      * Returns the appropriate {@code invoke-static} rop for the
   1974      * given type. The result is typically a newly-allocated instance.
   1975      *
   1976      * @param meth {@code non-null;} descriptor of the method
   1977      * @return {@code non-null;} an appropriate instance
   1978      */
   1979     public static Rop opInvokeStatic(Prototype meth) {
   1980         return new Rop(RegOps.INVOKE_STATIC,
   1981                        meth.getParameterFrameTypes(),
   1982                        StdTypeList.THROWABLE);
   1983     }
   1984 
   1985     /**
   1986      * Returns the appropriate {@code invoke-virtual} rop for the
   1987      * given type. The result is typically a newly-allocated instance.
   1988      *
   1989      * @param meth {@code non-null;} descriptor of the method, including the
   1990      * {@code this} parameter
   1991      * @return {@code non-null;} an appropriate instance
   1992      */
   1993     public static Rop opInvokeVirtual(Prototype meth) {
   1994         return new Rop(RegOps.INVOKE_VIRTUAL,
   1995                        meth.getParameterFrameTypes(),
   1996                        StdTypeList.THROWABLE);
   1997     }
   1998 
   1999     /**
   2000      * Returns the appropriate {@code invoke-super} rop for the
   2001      * given type. The result is typically a newly-allocated instance.
   2002      *
   2003      * @param meth {@code non-null;} descriptor of the method, including the
   2004      * {@code this} parameter
   2005      * @return {@code non-null;} an appropriate instance
   2006      */
   2007     public static Rop opInvokeSuper(Prototype meth) {
   2008         return new Rop(RegOps.INVOKE_SUPER,
   2009                        meth.getParameterFrameTypes(),
   2010                        StdTypeList.THROWABLE);
   2011     }
   2012 
   2013     /**
   2014      * Returns the appropriate {@code invoke-direct} rop for the
   2015      * given type. The result is typically a newly-allocated instance.
   2016      *
   2017      * @param meth {@code non-null;} descriptor of the method, including the
   2018      * {@code this} parameter
   2019      * @return {@code non-null;} an appropriate instance
   2020      */
   2021     public static Rop opInvokeDirect(Prototype meth) {
   2022         return new Rop(RegOps.INVOKE_DIRECT,
   2023                        meth.getParameterFrameTypes(),
   2024                        StdTypeList.THROWABLE);
   2025     }
   2026 
   2027     /**
   2028      * Returns the appropriate {@code invoke-interface} rop for the
   2029      * given type. The result is typically a newly-allocated instance.
   2030      *
   2031      * @param meth {@code non-null;} descriptor of the method, including the
   2032      * {@code this} parameter
   2033      * @return {@code non-null;} an appropriate instance
   2034      */
   2035     public static Rop opInvokeInterface(Prototype meth) {
   2036         return new Rop(RegOps.INVOKE_INTERFACE,
   2037                        meth.getParameterFrameTypes(),
   2038                        StdTypeList.THROWABLE);
   2039     }
   2040 
   2041     /**
   2042      * Returns the appropriate {@code mark-local} rop for the given type.
   2043      * The result is a shared instance.
   2044      *
   2045      * @param type {@code non-null;} type of value being marked
   2046      * @return {@code non-null;} an appropriate instance
   2047      */
   2048     public static Rop opMarkLocal(TypeBearer type) {
   2049         switch (type.getBasicFrameType()) {
   2050             case Type.BT_INT:    return MARK_LOCAL_INT;
   2051             case Type.BT_LONG:   return MARK_LOCAL_LONG;
   2052             case Type.BT_FLOAT:  return MARK_LOCAL_FLOAT;
   2053             case Type.BT_DOUBLE: return MARK_LOCAL_DOUBLE;
   2054             case Type.BT_OBJECT: return MARK_LOCAL_OBJECT;
   2055         }
   2056 
   2057         return throwBadType(type);
   2058     }
   2059 
   2060     /**
   2061      * This class is uninstantiable.
   2062      */
   2063     private Rops() {
   2064         // This space intentionally left blank.
   2065     }
   2066 
   2067     /**
   2068      * Throws the right exception to complain about a bogus type.
   2069      *
   2070      * @param type {@code non-null;} the bad type
   2071      * @return never
   2072      */
   2073     private static Rop throwBadType(TypeBearer type) {
   2074         throw new IllegalArgumentException("bad type: " + type);
   2075     }
   2076 
   2077     /**
   2078      * Throws the right exception to complain about a bogus list of types.
   2079      *
   2080      * @param types {@code non-null;} the bad types
   2081      * @return never
   2082      */
   2083     private static Rop throwBadTypes(TypeList types) {
   2084         throw new IllegalArgumentException("bad types: " + types);
   2085     }
   2086 }
   2087