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