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