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