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