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 */ ropFor(int opcode, TypeBearer dest, TypeList sources, Constant cst)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 */ opMove(TypeBearer type)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 */ opMoveParam(TypeBearer type)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 */ opMoveException(TypeBearer type)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 */ opMoveResult(TypeBearer type)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 */ opMoveResultPseudo(TypeBearer type)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 */ opConst(TypeBearer type)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 */ opIfEq(TypeList types)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 */ opIfNe(TypeList types)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 */ opIfLt(TypeList types)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 */ opIfGe(TypeList types)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 */ opIfGt(TypeList types)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 */ opIfLe(TypeList types)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 */ pickIf(TypeList types, Rop intZ, Rop objZ, Rop intInt, Rop objObj)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 */ opAdd(TypeList types)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 */ opSub(TypeList types)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 */ opMul(TypeList types)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 */ opDiv(TypeList types)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 */ opRem(TypeList types)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 */ opAnd(TypeList types)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 */ opOr(TypeList types)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 */ opXor(TypeList types)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 */ opShl(TypeList types)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 */ opShr(TypeList types)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 */ opUshr(TypeList types)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 */ pickBinaryOp(TypeList types, Rop int1, Rop long1, Rop float1, Rop double1, Rop int2, Rop long2, Rop float2, Rop double2)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 */ opNeg(TypeBearer type)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 */ opNot(TypeBearer type)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 */ opCmpl(TypeBearer type)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 */ opCmpg(TypeBearer type)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 */ opConv(TypeBearer dest, TypeBearer source)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 default: break; 1724 } 1725 } 1726 case Type.BT_LONG: { 1727 switch (dbt) { 1728 case Type.BT_INT: return CONV_L2I; 1729 case Type.BT_FLOAT: return CONV_L2F; 1730 case Type.BT_DOUBLE: return CONV_L2D; 1731 default: break; 1732 } 1733 } 1734 case Type.BT_FLOAT: { 1735 switch (dbt) { 1736 case Type.BT_INT: return CONV_F2I; 1737 case Type.BT_LONG: return CONV_F2L; 1738 case Type.BT_DOUBLE: return CONV_F2D; 1739 default: break; 1740 } 1741 } 1742 case Type.BT_DOUBLE: { 1743 switch (dbt) { 1744 case Type.BT_INT: return CONV_D2I; 1745 case Type.BT_LONG: return CONV_D2L; 1746 case Type.BT_FLOAT: return CONV_D2F; 1747 default: break; 1748 } 1749 } 1750 } 1751 1752 return throwBadTypes(StdTypeList.make(dest.getType(), 1753 source.getType())); 1754 } 1755 1756 /** 1757 * Returns the appropriate {@code return} rop for the given type. The 1758 * result is a shared instance. 1759 * 1760 * @param type {@code non-null;} type of value being returned 1761 * @return {@code non-null;} an appropriate instance 1762 */ opReturn(TypeBearer type)1763 public static Rop opReturn(TypeBearer type) { 1764 switch (type.getBasicFrameType()) { 1765 case Type.BT_INT: return RETURN_INT; 1766 case Type.BT_LONG: return RETURN_LONG; 1767 case Type.BT_FLOAT: return RETURN_FLOAT; 1768 case Type.BT_DOUBLE: return RETURN_DOUBLE; 1769 case Type.BT_OBJECT: return RETURN_OBJECT; 1770 case Type.BT_VOID: return RETURN_VOID; 1771 } 1772 1773 return throwBadType(type); 1774 } 1775 1776 /** 1777 * Returns the appropriate {@code aget} rop for the given type. The 1778 * result is a shared instance. 1779 * 1780 * @param type {@code non-null;} element type of array being accessed 1781 * @return {@code non-null;} an appropriate instance 1782 */ opAget(TypeBearer type)1783 public static Rop opAget(TypeBearer type) { 1784 switch (type.getBasicType()) { 1785 case Type.BT_INT: return AGET_INT; 1786 case Type.BT_LONG: return AGET_LONG; 1787 case Type.BT_FLOAT: return AGET_FLOAT; 1788 case Type.BT_DOUBLE: return AGET_DOUBLE; 1789 case Type.BT_OBJECT: return AGET_OBJECT; 1790 case Type.BT_BOOLEAN: return AGET_BOOLEAN; 1791 case Type.BT_BYTE: return AGET_BYTE; 1792 case Type.BT_CHAR: return AGET_CHAR; 1793 case Type.BT_SHORT: return AGET_SHORT; 1794 } 1795 1796 return throwBadType(type); 1797 } 1798 1799 /** 1800 * Returns the appropriate {@code aput} rop for the given type. The 1801 * result is a shared instance. 1802 * 1803 * @param type {@code non-null;} element type of array being accessed 1804 * @return {@code non-null;} an appropriate instance 1805 */ opAput(TypeBearer type)1806 public static Rop opAput(TypeBearer type) { 1807 switch (type.getBasicType()) { 1808 case Type.BT_INT: return APUT_INT; 1809 case Type.BT_LONG: return APUT_LONG; 1810 case Type.BT_FLOAT: return APUT_FLOAT; 1811 case Type.BT_DOUBLE: return APUT_DOUBLE; 1812 case Type.BT_OBJECT: return APUT_OBJECT; 1813 case Type.BT_BOOLEAN: return APUT_BOOLEAN; 1814 case Type.BT_BYTE: return APUT_BYTE; 1815 case Type.BT_CHAR: return APUT_CHAR; 1816 case Type.BT_SHORT: return APUT_SHORT; 1817 } 1818 1819 return throwBadType(type); 1820 } 1821 1822 /** 1823 * Returns the appropriate {@code new-array} rop for the given 1824 * type. The result is a shared instance. 1825 * 1826 * @param arrayType {@code non-null;} array type of array being created 1827 * @return {@code non-null;} an appropriate instance 1828 */ opNewArray(TypeBearer arrayType)1829 public static Rop opNewArray(TypeBearer arrayType) { 1830 Type type = arrayType.getType(); 1831 Type elementType = type.getComponentType(); 1832 1833 switch (elementType.getBasicType()) { 1834 case Type.BT_INT: return NEW_ARRAY_INT; 1835 case Type.BT_LONG: return NEW_ARRAY_LONG; 1836 case Type.BT_FLOAT: return NEW_ARRAY_FLOAT; 1837 case Type.BT_DOUBLE: return NEW_ARRAY_DOUBLE; 1838 case Type.BT_BOOLEAN: return NEW_ARRAY_BOOLEAN; 1839 case Type.BT_BYTE: return NEW_ARRAY_BYTE; 1840 case Type.BT_CHAR: return NEW_ARRAY_CHAR; 1841 case Type.BT_SHORT: return NEW_ARRAY_SHORT; 1842 case Type.BT_OBJECT: { 1843 return new Rop(RegOps.NEW_ARRAY, type, StdTypeList.INT, 1844 Exceptions.LIST_Error_NegativeArraySizeException, 1845 "new-array-object"); 1846 } 1847 } 1848 1849 return throwBadType(type); 1850 } 1851 1852 /** 1853 * Returns the appropriate {@code filled-new-array} rop for the given 1854 * type. The result may be a shared instance. 1855 * 1856 * @param arrayType {@code non-null;} type of array being created 1857 * @param count {@code >= 0;} number of elements that the array should have 1858 * @return {@code non-null;} an appropriate instance 1859 */ opFilledNewArray(TypeBearer arrayType, int count)1860 public static Rop opFilledNewArray(TypeBearer arrayType, int count) { 1861 Type type = arrayType.getType(); 1862 Type elementType = type.getComponentType(); 1863 1864 if (elementType.isCategory2()) { 1865 return throwBadType(arrayType); 1866 } 1867 1868 if (count < 0) { 1869 throw new IllegalArgumentException("count < 0"); 1870 } 1871 1872 StdTypeList sourceTypes = new StdTypeList(count); 1873 1874 for (int i = 0; i < count; i++) { 1875 sourceTypes.set(i, elementType); 1876 } 1877 1878 // Note: The resulting rop is considered call-like. 1879 return new Rop(RegOps.FILLED_NEW_ARRAY, 1880 sourceTypes, 1881 Exceptions.LIST_Error); 1882 } 1883 1884 /** 1885 * Returns the appropriate {@code get-field} rop for the given 1886 * type. The result is a shared instance. 1887 * 1888 * @param type {@code non-null;} type of the field in question 1889 * @return {@code non-null;} an appropriate instance 1890 */ opGetField(TypeBearer type)1891 public static Rop opGetField(TypeBearer type) { 1892 switch (type.getBasicType()) { 1893 case Type.BT_INT: return GET_FIELD_INT; 1894 case Type.BT_LONG: return GET_FIELD_LONG; 1895 case Type.BT_FLOAT: return GET_FIELD_FLOAT; 1896 case Type.BT_DOUBLE: return GET_FIELD_DOUBLE; 1897 case Type.BT_OBJECT: return GET_FIELD_OBJECT; 1898 case Type.BT_BOOLEAN: return GET_FIELD_BOOLEAN; 1899 case Type.BT_BYTE: return GET_FIELD_BYTE; 1900 case Type.BT_CHAR: return GET_FIELD_CHAR; 1901 case Type.BT_SHORT: return GET_FIELD_SHORT; 1902 } 1903 1904 return throwBadType(type); 1905 } 1906 1907 /** 1908 * Returns the appropriate {@code put-field} rop for the given 1909 * type. The result is a shared instance. 1910 * 1911 * @param type {@code non-null;} type of the field in question 1912 * @return {@code non-null;} an appropriate instance 1913 */ opPutField(TypeBearer type)1914 public static Rop opPutField(TypeBearer type) { 1915 switch (type.getBasicType()) { 1916 case Type.BT_INT: return PUT_FIELD_INT; 1917 case Type.BT_LONG: return PUT_FIELD_LONG; 1918 case Type.BT_FLOAT: return PUT_FIELD_FLOAT; 1919 case Type.BT_DOUBLE: return PUT_FIELD_DOUBLE; 1920 case Type.BT_OBJECT: return PUT_FIELD_OBJECT; 1921 case Type.BT_BOOLEAN: return PUT_FIELD_BOOLEAN; 1922 case Type.BT_BYTE: return PUT_FIELD_BYTE; 1923 case Type.BT_CHAR: return PUT_FIELD_CHAR; 1924 case Type.BT_SHORT: return PUT_FIELD_SHORT; 1925 } 1926 1927 return throwBadType(type); 1928 } 1929 1930 /** 1931 * Returns the appropriate {@code get-static} rop for the given 1932 * type. The result is a shared instance. 1933 * 1934 * @param type {@code non-null;} type of the field in question 1935 * @return {@code non-null;} an appropriate instance 1936 */ opGetStatic(TypeBearer type)1937 public static Rop opGetStatic(TypeBearer type) { 1938 switch (type.getBasicType()) { 1939 case Type.BT_INT: return GET_STATIC_INT; 1940 case Type.BT_LONG: return GET_STATIC_LONG; 1941 case Type.BT_FLOAT: return GET_STATIC_FLOAT; 1942 case Type.BT_DOUBLE: return GET_STATIC_DOUBLE; 1943 case Type.BT_OBJECT: return GET_STATIC_OBJECT; 1944 case Type.BT_BOOLEAN: return GET_STATIC_BOOLEAN; 1945 case Type.BT_BYTE: return GET_STATIC_BYTE; 1946 case Type.BT_CHAR: return GET_STATIC_CHAR; 1947 case Type.BT_SHORT: return GET_STATIC_SHORT; 1948 } 1949 1950 return throwBadType(type); 1951 } 1952 1953 /** 1954 * Returns the appropriate {@code put-static} rop for the given 1955 * type. The result is a shared instance. 1956 * 1957 * @param type {@code non-null;} type of the field in question 1958 * @return {@code non-null;} an appropriate instance 1959 */ opPutStatic(TypeBearer type)1960 public static Rop opPutStatic(TypeBearer type) { 1961 switch (type.getBasicType()) { 1962 case Type.BT_INT: return PUT_STATIC_INT; 1963 case Type.BT_LONG: return PUT_STATIC_LONG; 1964 case Type.BT_FLOAT: return PUT_STATIC_FLOAT; 1965 case Type.BT_DOUBLE: return PUT_STATIC_DOUBLE; 1966 case Type.BT_OBJECT: return PUT_STATIC_OBJECT; 1967 case Type.BT_BOOLEAN: return PUT_STATIC_BOOLEAN; 1968 case Type.BT_BYTE: return PUT_STATIC_BYTE; 1969 case Type.BT_CHAR: return PUT_STATIC_CHAR; 1970 case Type.BT_SHORT: return PUT_STATIC_SHORT; 1971 } 1972 1973 return throwBadType(type); 1974 } 1975 1976 /** 1977 * Returns the appropriate {@code invoke-static} rop for the 1978 * given type. The result is typically a newly-allocated instance. 1979 * 1980 * @param meth {@code non-null;} descriptor of the method 1981 * @return {@code non-null;} an appropriate instance 1982 */ opInvokeStatic(Prototype meth)1983 public static Rop opInvokeStatic(Prototype meth) { 1984 return new Rop(RegOps.INVOKE_STATIC, 1985 meth.getParameterFrameTypes(), 1986 StdTypeList.THROWABLE); 1987 } 1988 1989 /** 1990 * Returns the appropriate {@code invoke-virtual} rop for the 1991 * given type. The result is typically a newly-allocated instance. 1992 * 1993 * @param meth {@code non-null;} descriptor of the method, including the 1994 * {@code this} parameter 1995 * @return {@code non-null;} an appropriate instance 1996 */ opInvokeVirtual(Prototype meth)1997 public static Rop opInvokeVirtual(Prototype meth) { 1998 return new Rop(RegOps.INVOKE_VIRTUAL, 1999 meth.getParameterFrameTypes(), 2000 StdTypeList.THROWABLE); 2001 } 2002 2003 /** 2004 * Returns the appropriate {@code invoke-super} rop for the 2005 * given type. The result is typically a newly-allocated instance. 2006 * 2007 * @param meth {@code non-null;} descriptor of the method, including the 2008 * {@code this} parameter 2009 * @return {@code non-null;} an appropriate instance 2010 */ opInvokeSuper(Prototype meth)2011 public static Rop opInvokeSuper(Prototype meth) { 2012 return new Rop(RegOps.INVOKE_SUPER, 2013 meth.getParameterFrameTypes(), 2014 StdTypeList.THROWABLE); 2015 } 2016 2017 /** 2018 * Returns the appropriate {@code invoke-direct} rop for the 2019 * given type. The result is typically a newly-allocated instance. 2020 * 2021 * @param meth {@code non-null;} descriptor of the method, including the 2022 * {@code this} parameter 2023 * @return {@code non-null;} an appropriate instance 2024 */ opInvokeDirect(Prototype meth)2025 public static Rop opInvokeDirect(Prototype meth) { 2026 return new Rop(RegOps.INVOKE_DIRECT, 2027 meth.getParameterFrameTypes(), 2028 StdTypeList.THROWABLE); 2029 } 2030 2031 /** 2032 * Returns the appropriate {@code invoke-interface} rop for the 2033 * given type. The result is typically a newly-allocated instance. 2034 * 2035 * @param meth {@code non-null;} descriptor of the method, including the 2036 * {@code this} parameter 2037 * @return {@code non-null;} an appropriate instance 2038 */ opInvokeInterface(Prototype meth)2039 public static Rop opInvokeInterface(Prototype meth) { 2040 return new Rop(RegOps.INVOKE_INTERFACE, 2041 meth.getParameterFrameTypes(), 2042 StdTypeList.THROWABLE); 2043 } 2044 2045 /** 2046 * Returns the appropriate {@code mark-local} rop for the given type. 2047 * The result is a shared instance. 2048 * 2049 * @param type {@code non-null;} type of value being marked 2050 * @return {@code non-null;} an appropriate instance 2051 */ opMarkLocal(TypeBearer type)2052 public static Rop opMarkLocal(TypeBearer type) { 2053 switch (type.getBasicFrameType()) { 2054 case Type.BT_INT: return MARK_LOCAL_INT; 2055 case Type.BT_LONG: return MARK_LOCAL_LONG; 2056 case Type.BT_FLOAT: return MARK_LOCAL_FLOAT; 2057 case Type.BT_DOUBLE: return MARK_LOCAL_DOUBLE; 2058 case Type.BT_OBJECT: return MARK_LOCAL_OBJECT; 2059 } 2060 2061 return throwBadType(type); 2062 } 2063 2064 /** 2065 * This class is uninstantiable. 2066 */ Rops()2067 private Rops() { 2068 // This space intentionally left blank. 2069 } 2070 2071 /** 2072 * Throws the right exception to complain about a bogus type. 2073 * 2074 * @param type {@code non-null;} the bad type 2075 * @return never 2076 */ throwBadType(TypeBearer type)2077 private static Rop throwBadType(TypeBearer type) { 2078 throw new IllegalArgumentException("bad type: " + type); 2079 } 2080 2081 /** 2082 * Throws the right exception to complain about a bogus list of types. 2083 * 2084 * @param types {@code non-null;} the bad types 2085 * @return never 2086 */ throwBadTypes(TypeList types)2087 private static Rop throwBadTypes(TypeList types) { 2088 throw new IllegalArgumentException("bad types: " + types); 2089 } 2090 } 2091