xref: /aosp_15_r20/external/javassist/src/main/javassist/compiler/JvstCodeGen.java (revision f1fbf3c2ab775ce834e0af96b7a85bdc7a0eac65)
1*f1fbf3c2SXin Li /*
2*f1fbf3c2SXin Li  * Javassist, a Java-bytecode translator toolkit.
3*f1fbf3c2SXin Li  * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
4*f1fbf3c2SXin Li  *
5*f1fbf3c2SXin Li  * The contents of this file are subject to the Mozilla Public License Version
6*f1fbf3c2SXin Li  * 1.1 (the "License"); you may not use this file except in compliance with
7*f1fbf3c2SXin Li  * the License.  Alternatively, the contents of this file may be used under
8*f1fbf3c2SXin Li  * the terms of the GNU Lesser General Public License Version 2.1 or later,
9*f1fbf3c2SXin Li  * or the Apache License Version 2.0.
10*f1fbf3c2SXin Li  *
11*f1fbf3c2SXin Li  * Software distributed under the License is distributed on an "AS IS" basis,
12*f1fbf3c2SXin Li  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13*f1fbf3c2SXin Li  * for the specific language governing rights and limitations under the
14*f1fbf3c2SXin Li  * License.
15*f1fbf3c2SXin Li  */
16*f1fbf3c2SXin Li 
17*f1fbf3c2SXin Li package javassist.compiler;
18*f1fbf3c2SXin Li 
19*f1fbf3c2SXin Li import javassist.ClassPool;
20*f1fbf3c2SXin Li import javassist.CtClass;
21*f1fbf3c2SXin Li import javassist.CtPrimitiveType;
22*f1fbf3c2SXin Li import javassist.NotFoundException;
23*f1fbf3c2SXin Li import javassist.bytecode.Bytecode;
24*f1fbf3c2SXin Li import javassist.bytecode.Descriptor;
25*f1fbf3c2SXin Li import javassist.compiler.ast.ASTList;
26*f1fbf3c2SXin Li import javassist.compiler.ast.ASTree;
27*f1fbf3c2SXin Li import javassist.compiler.ast.CallExpr;
28*f1fbf3c2SXin Li import javassist.compiler.ast.CastExpr;
29*f1fbf3c2SXin Li import javassist.compiler.ast.Declarator;
30*f1fbf3c2SXin Li import javassist.compiler.ast.Expr;
31*f1fbf3c2SXin Li import javassist.compiler.ast.Member;
32*f1fbf3c2SXin Li import javassist.compiler.ast.Stmnt;
33*f1fbf3c2SXin Li import javassist.compiler.ast.Symbol;
34*f1fbf3c2SXin Li 
35*f1fbf3c2SXin Li /* Code generator accepting extended Java syntax for Javassist.
36*f1fbf3c2SXin Li  */
37*f1fbf3c2SXin Li 
38*f1fbf3c2SXin Li public class JvstCodeGen extends MemberCodeGen {
39*f1fbf3c2SXin Li     String paramArrayName = null;
40*f1fbf3c2SXin Li     String paramListName = null;
41*f1fbf3c2SXin Li     CtClass[] paramTypeList = null;
42*f1fbf3c2SXin Li     private int paramVarBase = 0;       // variable index for $0 or $1.
43*f1fbf3c2SXin Li     private boolean useParam0 = false;  // true if $0 is used.
44*f1fbf3c2SXin Li     private String param0Type = null;   // JVM name
45*f1fbf3c2SXin Li     public static final String sigName = "$sig";
46*f1fbf3c2SXin Li     public static final String dollarTypeName = "$type";
47*f1fbf3c2SXin Li     public static final String clazzName = "$class";
48*f1fbf3c2SXin Li     private CtClass dollarType = null;
49*f1fbf3c2SXin Li     CtClass returnType = null;
50*f1fbf3c2SXin Li     String returnCastName = null;
51*f1fbf3c2SXin Li     @SuppressWarnings("unused")
52*f1fbf3c2SXin Li     private String returnVarName = null;        // null if $_ is not used.
53*f1fbf3c2SXin Li     public static final String wrapperCastName = "$w";
54*f1fbf3c2SXin Li     String proceedName = null;
55*f1fbf3c2SXin Li     public static final String cflowName = "$cflow";
56*f1fbf3c2SXin Li     ProceedHandler procHandler = null;  // null if not used.
57*f1fbf3c2SXin Li 
JvstCodeGen(Bytecode b, CtClass cc, ClassPool cp)58*f1fbf3c2SXin Li     public JvstCodeGen(Bytecode b, CtClass cc, ClassPool cp) {
59*f1fbf3c2SXin Li         super(b, cc, cp);
60*f1fbf3c2SXin Li         setTypeChecker(new JvstTypeChecker(cc, cp, this));
61*f1fbf3c2SXin Li     }
62*f1fbf3c2SXin Li 
63*f1fbf3c2SXin Li     /* Index of $1.
64*f1fbf3c2SXin Li      */
indexOfParam1()65*f1fbf3c2SXin Li     private int indexOfParam1() {
66*f1fbf3c2SXin Li         return paramVarBase + (useParam0 ? 1 : 0);
67*f1fbf3c2SXin Li     }
68*f1fbf3c2SXin Li 
69*f1fbf3c2SXin Li     /* Records a ProceedHandler obejct.
70*f1fbf3c2SXin Li      *
71*f1fbf3c2SXin Li      * @param name      the name of the special method call.
72*f1fbf3c2SXin Li      *                  it is usually $proceed.
73*f1fbf3c2SXin Li      */
setProceedHandler(ProceedHandler h, String name)74*f1fbf3c2SXin Li     public void setProceedHandler(ProceedHandler h, String name) {
75*f1fbf3c2SXin Li         proceedName = name;
76*f1fbf3c2SXin Li         procHandler = h;
77*f1fbf3c2SXin Li     }
78*f1fbf3c2SXin Li 
79*f1fbf3c2SXin Li     /* If the type of the expression compiled last is void,
80*f1fbf3c2SXin Li      * add ACONST_NULL and change exprType, arrayDim, className.
81*f1fbf3c2SXin Li      */
addNullIfVoid()82*f1fbf3c2SXin Li     public void addNullIfVoid() {
83*f1fbf3c2SXin Li         if (exprType == VOID) {
84*f1fbf3c2SXin Li             bytecode.addOpcode(ACONST_NULL);
85*f1fbf3c2SXin Li             exprType = CLASS;
86*f1fbf3c2SXin Li             arrayDim = 0;
87*f1fbf3c2SXin Li             className = jvmJavaLangObject;
88*f1fbf3c2SXin Li         }
89*f1fbf3c2SXin Li     }
90*f1fbf3c2SXin Li 
91*f1fbf3c2SXin Li     /* To support $args, $sig, and $type.
92*f1fbf3c2SXin Li      * $args is an array of parameter list.
93*f1fbf3c2SXin Li      */
94*f1fbf3c2SXin Li     @Override
atMember(Member mem)95*f1fbf3c2SXin Li     public void atMember(Member mem) throws CompileError {
96*f1fbf3c2SXin Li         String name = mem.get();
97*f1fbf3c2SXin Li         if (name.equals(paramArrayName)) {
98*f1fbf3c2SXin Li             compileParameterList(bytecode, paramTypeList, indexOfParam1());
99*f1fbf3c2SXin Li             exprType = CLASS;
100*f1fbf3c2SXin Li             arrayDim = 1;
101*f1fbf3c2SXin Li             className = jvmJavaLangObject;
102*f1fbf3c2SXin Li         }
103*f1fbf3c2SXin Li         else if (name.equals(sigName)) {
104*f1fbf3c2SXin Li             bytecode.addLdc(Descriptor.ofMethod(returnType, paramTypeList));
105*f1fbf3c2SXin Li             bytecode.addInvokestatic("javassist/runtime/Desc", "getParams",
106*f1fbf3c2SXin Li                                 "(Ljava/lang/String;)[Ljava/lang/Class;");
107*f1fbf3c2SXin Li             exprType = CLASS;
108*f1fbf3c2SXin Li             arrayDim = 1;
109*f1fbf3c2SXin Li             className = "java/lang/Class";
110*f1fbf3c2SXin Li         }
111*f1fbf3c2SXin Li         else if (name.equals(dollarTypeName)) {
112*f1fbf3c2SXin Li             if (dollarType == null)
113*f1fbf3c2SXin Li                 throw new CompileError(dollarTypeName + " is not available");
114*f1fbf3c2SXin Li 
115*f1fbf3c2SXin Li             bytecode.addLdc(Descriptor.of(dollarType));
116*f1fbf3c2SXin Li             callGetType("getType");
117*f1fbf3c2SXin Li         }
118*f1fbf3c2SXin Li         else if (name.equals(clazzName)) {
119*f1fbf3c2SXin Li             if (param0Type == null)
120*f1fbf3c2SXin Li                 throw new CompileError(clazzName + " is not available");
121*f1fbf3c2SXin Li 
122*f1fbf3c2SXin Li             bytecode.addLdc(param0Type);
123*f1fbf3c2SXin Li             callGetType("getClazz");
124*f1fbf3c2SXin Li         }
125*f1fbf3c2SXin Li         else
126*f1fbf3c2SXin Li             super.atMember(mem);
127*f1fbf3c2SXin Li     }
128*f1fbf3c2SXin Li 
callGetType(String method)129*f1fbf3c2SXin Li     private void callGetType(String method) {
130*f1fbf3c2SXin Li         bytecode.addInvokestatic("javassist/runtime/Desc", method,
131*f1fbf3c2SXin Li                                 "(Ljava/lang/String;)Ljava/lang/Class;");
132*f1fbf3c2SXin Li         exprType = CLASS;
133*f1fbf3c2SXin Li         arrayDim = 0;
134*f1fbf3c2SXin Li         className = "java/lang/Class";
135*f1fbf3c2SXin Li     }
136*f1fbf3c2SXin Li 
137*f1fbf3c2SXin Li     @Override
atFieldAssign(Expr expr, int op, ASTree left, ASTree right, boolean doDup)138*f1fbf3c2SXin Li     protected void atFieldAssign(Expr expr, int op, ASTree left,
139*f1fbf3c2SXin Li                         ASTree right, boolean doDup) throws CompileError
140*f1fbf3c2SXin Li     {
141*f1fbf3c2SXin Li         if (left instanceof Member
142*f1fbf3c2SXin Li             && ((Member)left).get().equals(paramArrayName)) {
143*f1fbf3c2SXin Li             if (op != '=')
144*f1fbf3c2SXin Li                 throw new CompileError("bad operator for " + paramArrayName);
145*f1fbf3c2SXin Li 
146*f1fbf3c2SXin Li             right.accept(this);
147*f1fbf3c2SXin Li             if (arrayDim != 1 || exprType != CLASS)
148*f1fbf3c2SXin Li                 throw new CompileError("invalid type for " + paramArrayName);
149*f1fbf3c2SXin Li 
150*f1fbf3c2SXin Li             atAssignParamList(paramTypeList, bytecode);
151*f1fbf3c2SXin Li             if (!doDup)
152*f1fbf3c2SXin Li                 bytecode.addOpcode(POP);
153*f1fbf3c2SXin Li         }
154*f1fbf3c2SXin Li         else
155*f1fbf3c2SXin Li             super.atFieldAssign(expr, op, left, right, doDup);
156*f1fbf3c2SXin Li     }
157*f1fbf3c2SXin Li 
atAssignParamList(CtClass[] params, Bytecode code)158*f1fbf3c2SXin Li     protected void atAssignParamList(CtClass[] params, Bytecode code)
159*f1fbf3c2SXin Li         throws CompileError
160*f1fbf3c2SXin Li     {
161*f1fbf3c2SXin Li         if (params == null)
162*f1fbf3c2SXin Li             return;
163*f1fbf3c2SXin Li 
164*f1fbf3c2SXin Li         int varNo = indexOfParam1();
165*f1fbf3c2SXin Li         int n = params.length;
166*f1fbf3c2SXin Li         for (int i = 0; i < n; ++i) {
167*f1fbf3c2SXin Li             code.addOpcode(DUP);
168*f1fbf3c2SXin Li             code.addIconst(i);
169*f1fbf3c2SXin Li             code.addOpcode(AALOAD);
170*f1fbf3c2SXin Li             compileUnwrapValue(params[i], code);
171*f1fbf3c2SXin Li             code.addStore(varNo, params[i]);
172*f1fbf3c2SXin Li             varNo += is2word(exprType, arrayDim) ? 2 : 1;
173*f1fbf3c2SXin Li         }
174*f1fbf3c2SXin Li     }
175*f1fbf3c2SXin Li 
176*f1fbf3c2SXin Li     @Override
atCastExpr(CastExpr expr)177*f1fbf3c2SXin Li     public void atCastExpr(CastExpr expr) throws CompileError {
178*f1fbf3c2SXin Li         ASTList classname = expr.getClassName();
179*f1fbf3c2SXin Li         if (classname != null && expr.getArrayDim() == 0) {
180*f1fbf3c2SXin Li             ASTree p = classname.head();
181*f1fbf3c2SXin Li             if (p instanceof Symbol && classname.tail() == null) {
182*f1fbf3c2SXin Li                 String typename = ((Symbol)p).get();
183*f1fbf3c2SXin Li                 if (typename.equals(returnCastName)) {
184*f1fbf3c2SXin Li                     atCastToRtype(expr);
185*f1fbf3c2SXin Li                     return;
186*f1fbf3c2SXin Li                 }
187*f1fbf3c2SXin Li                 else if (typename.equals(wrapperCastName)) {
188*f1fbf3c2SXin Li                     atCastToWrapper(expr);
189*f1fbf3c2SXin Li                     return;
190*f1fbf3c2SXin Li                 }
191*f1fbf3c2SXin Li             }
192*f1fbf3c2SXin Li         }
193*f1fbf3c2SXin Li 
194*f1fbf3c2SXin Li         super.atCastExpr(expr);
195*f1fbf3c2SXin Li     }
196*f1fbf3c2SXin Li 
197*f1fbf3c2SXin Li     /**
198*f1fbf3c2SXin Li      * Inserts a cast operator to the return type.
199*f1fbf3c2SXin Li      * If the return type is void, this does nothing.
200*f1fbf3c2SXin Li      */
atCastToRtype(CastExpr expr)201*f1fbf3c2SXin Li     protected void atCastToRtype(CastExpr expr) throws CompileError {
202*f1fbf3c2SXin Li         expr.getOprand().accept(this);
203*f1fbf3c2SXin Li         if (exprType == VOID || isRefType(exprType) || arrayDim > 0)
204*f1fbf3c2SXin Li             compileUnwrapValue(returnType, bytecode);
205*f1fbf3c2SXin Li         else if (returnType instanceof CtPrimitiveType) {
206*f1fbf3c2SXin Li             CtPrimitiveType pt = (CtPrimitiveType)returnType;
207*f1fbf3c2SXin Li             int destType = MemberResolver.descToType(pt.getDescriptor());
208*f1fbf3c2SXin Li             atNumCastExpr(exprType, destType);
209*f1fbf3c2SXin Li             exprType = destType;
210*f1fbf3c2SXin Li             arrayDim = 0;
211*f1fbf3c2SXin Li             className = null;
212*f1fbf3c2SXin Li         }
213*f1fbf3c2SXin Li         else
214*f1fbf3c2SXin Li             throw new CompileError("invalid cast");
215*f1fbf3c2SXin Li     }
216*f1fbf3c2SXin Li 
atCastToWrapper(CastExpr expr)217*f1fbf3c2SXin Li     protected void atCastToWrapper(CastExpr expr) throws CompileError {
218*f1fbf3c2SXin Li         expr.getOprand().accept(this);
219*f1fbf3c2SXin Li         if (isRefType(exprType) || arrayDim > 0)
220*f1fbf3c2SXin Li             return;     // Object type.  do nothing.
221*f1fbf3c2SXin Li 
222*f1fbf3c2SXin Li         CtClass clazz = resolver.lookupClass(exprType, arrayDim, className);
223*f1fbf3c2SXin Li         if (clazz instanceof CtPrimitiveType) {
224*f1fbf3c2SXin Li             CtPrimitiveType pt = (CtPrimitiveType)clazz;
225*f1fbf3c2SXin Li             String wrapper = pt.getWrapperName();
226*f1fbf3c2SXin Li             bytecode.addNew(wrapper);           // new <wrapper>
227*f1fbf3c2SXin Li             bytecode.addOpcode(DUP);            // dup
228*f1fbf3c2SXin Li             if (pt.getDataSize() > 1)
229*f1fbf3c2SXin Li                 bytecode.addOpcode(DUP2_X2);    // dup2_x2
230*f1fbf3c2SXin Li             else
231*f1fbf3c2SXin Li                 bytecode.addOpcode(DUP2_X1);    // dup2_x1
232*f1fbf3c2SXin Li 
233*f1fbf3c2SXin Li             bytecode.addOpcode(POP2);           // pop2
234*f1fbf3c2SXin Li             bytecode.addInvokespecial(wrapper, "<init>",
235*f1fbf3c2SXin Li                                       "(" + pt.getDescriptor() + ")V");
236*f1fbf3c2SXin Li                                                 // invokespecial
237*f1fbf3c2SXin Li             exprType = CLASS;
238*f1fbf3c2SXin Li             arrayDim = 0;
239*f1fbf3c2SXin Li             className = jvmJavaLangObject;
240*f1fbf3c2SXin Li         }
241*f1fbf3c2SXin Li     }
242*f1fbf3c2SXin Li 
243*f1fbf3c2SXin Li     /* Delegates to a ProcHandler object if the method call is
244*f1fbf3c2SXin Li      * $proceed().  It may process $cflow().
245*f1fbf3c2SXin Li      */
246*f1fbf3c2SXin Li     @Override
atCallExpr(CallExpr expr)247*f1fbf3c2SXin Li     public void atCallExpr(CallExpr expr) throws CompileError {
248*f1fbf3c2SXin Li         ASTree method = expr.oprand1();
249*f1fbf3c2SXin Li         if (method instanceof Member) {
250*f1fbf3c2SXin Li             String name = ((Member)method).get();
251*f1fbf3c2SXin Li             if (procHandler != null && name.equals(proceedName)) {
252*f1fbf3c2SXin Li                 procHandler.doit(this, bytecode, (ASTList)expr.oprand2());
253*f1fbf3c2SXin Li                 return;
254*f1fbf3c2SXin Li             }
255*f1fbf3c2SXin Li             else if (name.equals(cflowName)) {
256*f1fbf3c2SXin Li                 atCflow((ASTList)expr.oprand2());
257*f1fbf3c2SXin Li                 return;
258*f1fbf3c2SXin Li             }
259*f1fbf3c2SXin Li         }
260*f1fbf3c2SXin Li 
261*f1fbf3c2SXin Li         super.atCallExpr(expr);
262*f1fbf3c2SXin Li     }
263*f1fbf3c2SXin Li 
264*f1fbf3c2SXin Li     /* To support $cflow().
265*f1fbf3c2SXin Li      */
atCflow(ASTList cname)266*f1fbf3c2SXin Li     protected void atCflow(ASTList cname) throws CompileError {
267*f1fbf3c2SXin Li         StringBuffer sbuf = new StringBuffer();
268*f1fbf3c2SXin Li         if (cname == null || cname.tail() != null)
269*f1fbf3c2SXin Li             throw new CompileError("bad " + cflowName);
270*f1fbf3c2SXin Li 
271*f1fbf3c2SXin Li         makeCflowName(sbuf, cname.head());
272*f1fbf3c2SXin Li         String name = sbuf.toString();
273*f1fbf3c2SXin Li         Object[] names = resolver.getClassPool().lookupCflow(name);
274*f1fbf3c2SXin Li         if (names == null)
275*f1fbf3c2SXin Li             throw new CompileError("no such " + cflowName + ": " + name);
276*f1fbf3c2SXin Li 
277*f1fbf3c2SXin Li         bytecode.addGetstatic((String)names[0], (String)names[1],
278*f1fbf3c2SXin Li                               "Ljavassist/runtime/Cflow;");
279*f1fbf3c2SXin Li         bytecode.addInvokevirtual("javassist.runtime.Cflow",
280*f1fbf3c2SXin Li                                   "value", "()I");
281*f1fbf3c2SXin Li         exprType = INT;
282*f1fbf3c2SXin Li         arrayDim = 0;
283*f1fbf3c2SXin Li         className = null;
284*f1fbf3c2SXin Li     }
285*f1fbf3c2SXin Li 
286*f1fbf3c2SXin Li     /* Syntax:
287*f1fbf3c2SXin Li      *
288*f1fbf3c2SXin Li      * <cflow> : $cflow '(' <cflow name> ')'
289*f1fbf3c2SXin Li      * <cflow name> : <identifier> ('.' <identifier>)*
290*f1fbf3c2SXin Li      */
makeCflowName(StringBuffer sbuf, ASTree name)291*f1fbf3c2SXin Li     private static void makeCflowName(StringBuffer sbuf, ASTree name)
292*f1fbf3c2SXin Li         throws CompileError
293*f1fbf3c2SXin Li     {
294*f1fbf3c2SXin Li         if (name instanceof Symbol) {
295*f1fbf3c2SXin Li             sbuf.append(((Symbol)name).get());
296*f1fbf3c2SXin Li             return;
297*f1fbf3c2SXin Li         }
298*f1fbf3c2SXin Li         else if (name instanceof Expr) {
299*f1fbf3c2SXin Li             Expr expr = (Expr)name;
300*f1fbf3c2SXin Li             if (expr.getOperator() == '.') {
301*f1fbf3c2SXin Li                 makeCflowName(sbuf, expr.oprand1());
302*f1fbf3c2SXin Li                 sbuf.append('.');
303*f1fbf3c2SXin Li                 makeCflowName(sbuf, expr.oprand2());
304*f1fbf3c2SXin Li                 return;
305*f1fbf3c2SXin Li             }
306*f1fbf3c2SXin Li         }
307*f1fbf3c2SXin Li 
308*f1fbf3c2SXin Li         throw new CompileError("bad " + cflowName);
309*f1fbf3c2SXin Li     }
310*f1fbf3c2SXin Li 
311*f1fbf3c2SXin Li     /* To support $$.  ($$) is equivalent to ($1, ..., $n).
312*f1fbf3c2SXin Li      * It can be used only as a parameter list of method call.
313*f1fbf3c2SXin Li      */
isParamListName(ASTList args)314*f1fbf3c2SXin Li     public boolean isParamListName(ASTList args) {
315*f1fbf3c2SXin Li         if (paramTypeList != null
316*f1fbf3c2SXin Li             && args != null && args.tail() == null) {
317*f1fbf3c2SXin Li             ASTree left = args.head();
318*f1fbf3c2SXin Li             return (left instanceof Member
319*f1fbf3c2SXin Li                     && ((Member)left).get().equals(paramListName));
320*f1fbf3c2SXin Li         }
321*f1fbf3c2SXin Li         return false;
322*f1fbf3c2SXin Li     }
323*f1fbf3c2SXin Li 
324*f1fbf3c2SXin Li     /*
325*f1fbf3c2SXin Li     public int getMethodArgsLength(ASTList args) {
326*f1fbf3c2SXin Li         if (!isParamListName(args))
327*f1fbf3c2SXin Li             return super.getMethodArgsLength(args);
328*f1fbf3c2SXin Li 
329*f1fbf3c2SXin Li         return paramTypeList.length;
330*f1fbf3c2SXin Li     }
331*f1fbf3c2SXin Li     */
332*f1fbf3c2SXin Li 
333*f1fbf3c2SXin Li     @Override
getMethodArgsLength(ASTList args)334*f1fbf3c2SXin Li     public int getMethodArgsLength(ASTList args) {
335*f1fbf3c2SXin Li         String pname = paramListName;
336*f1fbf3c2SXin Li         int n = 0;
337*f1fbf3c2SXin Li         while (args != null) {
338*f1fbf3c2SXin Li             ASTree a = args.head();
339*f1fbf3c2SXin Li             if (a instanceof Member && ((Member)a).get().equals(pname)) {
340*f1fbf3c2SXin Li                 if (paramTypeList != null)
341*f1fbf3c2SXin Li                     n += paramTypeList.length;
342*f1fbf3c2SXin Li             }
343*f1fbf3c2SXin Li             else
344*f1fbf3c2SXin Li                 ++n;
345*f1fbf3c2SXin Li 
346*f1fbf3c2SXin Li             args = args.tail();
347*f1fbf3c2SXin Li         }
348*f1fbf3c2SXin Li 
349*f1fbf3c2SXin Li         return n;
350*f1fbf3c2SXin Li     }
351*f1fbf3c2SXin Li 
352*f1fbf3c2SXin Li     @Override
atMethodArgs(ASTList args, int[] types, int[] dims, String[] cnames)353*f1fbf3c2SXin Li     public void atMethodArgs(ASTList args, int[] types, int[] dims,
354*f1fbf3c2SXin Li                                 String[] cnames) throws CompileError {
355*f1fbf3c2SXin Li         CtClass[] params = paramTypeList;
356*f1fbf3c2SXin Li         String pname = paramListName;
357*f1fbf3c2SXin Li         int i = 0;
358*f1fbf3c2SXin Li         while (args != null) {
359*f1fbf3c2SXin Li             ASTree a = args.head();
360*f1fbf3c2SXin Li             if (a instanceof Member && ((Member)a).get().equals(pname)) {
361*f1fbf3c2SXin Li                 if (params != null) {
362*f1fbf3c2SXin Li                     int n = params.length;
363*f1fbf3c2SXin Li                     int regno = indexOfParam1();
364*f1fbf3c2SXin Li                     for (int k = 0; k < n; ++k) {
365*f1fbf3c2SXin Li                         CtClass p = params[k];
366*f1fbf3c2SXin Li                         regno += bytecode.addLoad(regno, p);
367*f1fbf3c2SXin Li                         setType(p);
368*f1fbf3c2SXin Li                         types[i] = exprType;
369*f1fbf3c2SXin Li                         dims[i] = arrayDim;
370*f1fbf3c2SXin Li                         cnames[i] = className;
371*f1fbf3c2SXin Li                         ++i;
372*f1fbf3c2SXin Li                     }
373*f1fbf3c2SXin Li                 }
374*f1fbf3c2SXin Li             }
375*f1fbf3c2SXin Li             else {
376*f1fbf3c2SXin Li                 a.accept(this);
377*f1fbf3c2SXin Li                 types[i] = exprType;
378*f1fbf3c2SXin Li                 dims[i] = arrayDim;
379*f1fbf3c2SXin Li                 cnames[i] = className;
380*f1fbf3c2SXin Li                 ++i;
381*f1fbf3c2SXin Li             }
382*f1fbf3c2SXin Li 
383*f1fbf3c2SXin Li             args = args.tail();
384*f1fbf3c2SXin Li         }
385*f1fbf3c2SXin Li     }
386*f1fbf3c2SXin Li 
387*f1fbf3c2SXin Li     /*
388*f1fbf3c2SXin Li     public void atMethodArgs(ASTList args, int[] types, int[] dims,
389*f1fbf3c2SXin Li                                 String[] cnames) throws CompileError {
390*f1fbf3c2SXin Li         if (!isParamListName(args)) {
391*f1fbf3c2SXin Li             super.atMethodArgs(args, types, dims, cnames);
392*f1fbf3c2SXin Li             return;
393*f1fbf3c2SXin Li         }
394*f1fbf3c2SXin Li 
395*f1fbf3c2SXin Li         CtClass[] params = paramTypeList;
396*f1fbf3c2SXin Li         if (params == null)
397*f1fbf3c2SXin Li             return;
398*f1fbf3c2SXin Li 
399*f1fbf3c2SXin Li         int n = params.length;
400*f1fbf3c2SXin Li         int regno = indexOfParam1();
401*f1fbf3c2SXin Li         for (int i = 0; i < n; ++i) {
402*f1fbf3c2SXin Li             CtClass p = params[i];
403*f1fbf3c2SXin Li             regno += bytecode.addLoad(regno, p);
404*f1fbf3c2SXin Li             setType(p);
405*f1fbf3c2SXin Li             types[i] = exprType;
406*f1fbf3c2SXin Li             dims[i] = arrayDim;
407*f1fbf3c2SXin Li             cnames[i] = className;
408*f1fbf3c2SXin Li         }
409*f1fbf3c2SXin Li     }
410*f1fbf3c2SXin Li     */
411*f1fbf3c2SXin Li 
412*f1fbf3c2SXin Li     /* called by Javac#recordSpecialProceed().
413*f1fbf3c2SXin Li      */
compileInvokeSpecial(ASTree target, int methodIndex, String descriptor, ASTList args)414*f1fbf3c2SXin Li     void compileInvokeSpecial(ASTree target, int methodIndex,
415*f1fbf3c2SXin Li                               String descriptor, ASTList args)
416*f1fbf3c2SXin Li         throws CompileError
417*f1fbf3c2SXin Li     {
418*f1fbf3c2SXin Li         target.accept(this);
419*f1fbf3c2SXin Li         int nargs = getMethodArgsLength(args);
420*f1fbf3c2SXin Li         atMethodArgs(args, new int[nargs], new int[nargs],
421*f1fbf3c2SXin Li                      new String[nargs]);
422*f1fbf3c2SXin Li         bytecode.addInvokespecial(methodIndex, descriptor);
423*f1fbf3c2SXin Li         setReturnType(descriptor, false, false);
424*f1fbf3c2SXin Li         addNullIfVoid();
425*f1fbf3c2SXin Li     }
426*f1fbf3c2SXin Li 
427*f1fbf3c2SXin Li     /*
428*f1fbf3c2SXin Li      * Makes it valid to write "return <expr>;" for a void method.
429*f1fbf3c2SXin Li      */
430*f1fbf3c2SXin Li     @Override
atReturnStmnt(Stmnt st)431*f1fbf3c2SXin Li     protected void atReturnStmnt(Stmnt st) throws CompileError {
432*f1fbf3c2SXin Li         ASTree result = st.getLeft();
433*f1fbf3c2SXin Li         if (result != null && returnType == CtClass.voidType) {
434*f1fbf3c2SXin Li             compileExpr(result);
435*f1fbf3c2SXin Li             if (is2word(exprType, arrayDim))
436*f1fbf3c2SXin Li                 bytecode.addOpcode(POP2);
437*f1fbf3c2SXin Li             else if (exprType != VOID)
438*f1fbf3c2SXin Li                 bytecode.addOpcode(POP);
439*f1fbf3c2SXin Li 
440*f1fbf3c2SXin Li             result = null;
441*f1fbf3c2SXin Li         }
442*f1fbf3c2SXin Li 
443*f1fbf3c2SXin Li         atReturnStmnt2(result);
444*f1fbf3c2SXin Li     }
445*f1fbf3c2SXin Li 
446*f1fbf3c2SXin Li     /**
447*f1fbf3c2SXin Li      * Makes a cast to the return type ($r) available.
448*f1fbf3c2SXin Li      * It also enables $_.
449*f1fbf3c2SXin Li      *
450*f1fbf3c2SXin Li      * <p>If the return type is void, ($r) does nothing.
451*f1fbf3c2SXin Li      * The type of $_ is java.lang.Object.
452*f1fbf3c2SXin Li      *
453*f1fbf3c2SXin Li      * @param resultName        null if $_ is not used.
454*f1fbf3c2SXin Li      * @return          -1 or the variable index assigned to $_.
455*f1fbf3c2SXin Li      */
recordReturnType(CtClass type, String castName, String resultName, SymbolTable tbl)456*f1fbf3c2SXin Li     public int recordReturnType(CtClass type, String castName,
457*f1fbf3c2SXin Li                  String resultName, SymbolTable tbl) throws CompileError
458*f1fbf3c2SXin Li     {
459*f1fbf3c2SXin Li         returnType = type;
460*f1fbf3c2SXin Li         returnCastName = castName;
461*f1fbf3c2SXin Li         returnVarName = resultName;
462*f1fbf3c2SXin Li         if (resultName == null)
463*f1fbf3c2SXin Li             return -1;
464*f1fbf3c2SXin Li         int varNo = getMaxLocals();
465*f1fbf3c2SXin Li         int locals = varNo + recordVar(type, resultName, varNo, tbl);
466*f1fbf3c2SXin Li         setMaxLocals(locals);
467*f1fbf3c2SXin Li         return varNo;
468*f1fbf3c2SXin Li     }
469*f1fbf3c2SXin Li 
470*f1fbf3c2SXin Li     /**
471*f1fbf3c2SXin Li      * Makes $type available.
472*f1fbf3c2SXin Li      */
recordType(CtClass t)473*f1fbf3c2SXin Li     public void recordType(CtClass t) {
474*f1fbf3c2SXin Li         dollarType = t;
475*f1fbf3c2SXin Li     }
476*f1fbf3c2SXin Li 
477*f1fbf3c2SXin Li     /**
478*f1fbf3c2SXin Li      * Makes method parameters $0, $1, ..., $args, $$, and $class available.
479*f1fbf3c2SXin Li      * $0 is equivalent to THIS if the method is not static.  Otherwise,
480*f1fbf3c2SXin Li      * if the method is static, then $0 is not available.
481*f1fbf3c2SXin Li      */
recordParams(CtClass[] params, boolean isStatic, String prefix, String paramVarName, String paramsName, SymbolTable tbl)482*f1fbf3c2SXin Li     public int recordParams(CtClass[] params, boolean isStatic,
483*f1fbf3c2SXin Li                              String prefix, String paramVarName,
484*f1fbf3c2SXin Li                              String paramsName, SymbolTable tbl)
485*f1fbf3c2SXin Li         throws CompileError
486*f1fbf3c2SXin Li     {
487*f1fbf3c2SXin Li         return recordParams(params, isStatic, prefix, paramVarName,
488*f1fbf3c2SXin Li                             paramsName, !isStatic, 0, getThisName(), tbl);
489*f1fbf3c2SXin Li     }
490*f1fbf3c2SXin Li 
491*f1fbf3c2SXin Li     /**
492*f1fbf3c2SXin Li      * Makes method parameters $0, $1, ..., $args, $$, and $class available.
493*f1fbf3c2SXin Li      * $0 is available only if use0 is true.  It might not be equivalent
494*f1fbf3c2SXin Li      * to THIS.
495*f1fbf3c2SXin Li      *
496*f1fbf3c2SXin Li      * @param params    the parameter types (the types of $1, $2, ..)
497*f1fbf3c2SXin Li      * @param prefix    it must be "$" (the first letter of $0, $1, ...)
498*f1fbf3c2SXin Li      * @param paramVarName      it must be "$args"
499*f1fbf3c2SXin Li      * @param paramsName        it must be "$$"
500*f1fbf3c2SXin Li      * @param use0      true if $0 is used.
501*f1fbf3c2SXin Li      * @param paramBase the register number of $0 (use0 is true)
502*f1fbf3c2SXin Li      *                          or $1 (otherwise).
503*f1fbf3c2SXin Li      * @param target    the class of $0.  If use0 is false, target
504*f1fbf3c2SXin Li      *                  can be null.  The value of "target" is also used
505*f1fbf3c2SXin Li      *                  as the name of the type represented by $class.
506*f1fbf3c2SXin Li      * @param isStatic  true if the method in which the compiled bytecode
507*f1fbf3c2SXin Li      *                  is embedded is static.
508*f1fbf3c2SXin Li      */
recordParams(CtClass[] params, boolean isStatic, String prefix, String paramVarName, String paramsName, boolean use0, int paramBase, String target, SymbolTable tbl)509*f1fbf3c2SXin Li     public int recordParams(CtClass[] params, boolean isStatic,
510*f1fbf3c2SXin Li                             String prefix, String paramVarName,
511*f1fbf3c2SXin Li                             String paramsName, boolean use0,
512*f1fbf3c2SXin Li                             int paramBase, String target,
513*f1fbf3c2SXin Li                             SymbolTable tbl)
514*f1fbf3c2SXin Li         throws CompileError
515*f1fbf3c2SXin Li     {
516*f1fbf3c2SXin Li         int varNo;
517*f1fbf3c2SXin Li 
518*f1fbf3c2SXin Li         paramTypeList = params;
519*f1fbf3c2SXin Li         paramArrayName = paramVarName;
520*f1fbf3c2SXin Li         paramListName = paramsName;
521*f1fbf3c2SXin Li         paramVarBase = paramBase;
522*f1fbf3c2SXin Li         useParam0 = use0;
523*f1fbf3c2SXin Li 
524*f1fbf3c2SXin Li         if (target != null)
525*f1fbf3c2SXin Li             param0Type = MemberResolver.jvmToJavaName(target);
526*f1fbf3c2SXin Li 
527*f1fbf3c2SXin Li         inStaticMethod = isStatic;
528*f1fbf3c2SXin Li         varNo = paramBase;
529*f1fbf3c2SXin Li         if (use0) {
530*f1fbf3c2SXin Li             String varName = prefix + "0";
531*f1fbf3c2SXin Li             Declarator decl
532*f1fbf3c2SXin Li                 = new Declarator(CLASS, MemberResolver.javaToJvmName(target),
533*f1fbf3c2SXin Li                                  0, varNo++, new Symbol(varName));
534*f1fbf3c2SXin Li             tbl.append(varName, decl);
535*f1fbf3c2SXin Li         }
536*f1fbf3c2SXin Li 
537*f1fbf3c2SXin Li         for (int i = 0; i < params.length; ++i)
538*f1fbf3c2SXin Li             varNo += recordVar(params[i], prefix + (i + 1), varNo, tbl);
539*f1fbf3c2SXin Li 
540*f1fbf3c2SXin Li         if (getMaxLocals() < varNo)
541*f1fbf3c2SXin Li             setMaxLocals(varNo);
542*f1fbf3c2SXin Li 
543*f1fbf3c2SXin Li         return varNo;
544*f1fbf3c2SXin Li     }
545*f1fbf3c2SXin Li 
546*f1fbf3c2SXin Li     /**
547*f1fbf3c2SXin Li      * Makes the given variable name available.
548*f1fbf3c2SXin Li      *
549*f1fbf3c2SXin Li      * @param type      variable type
550*f1fbf3c2SXin Li      * @param varName   variable name
551*f1fbf3c2SXin Li      */
recordVariable(CtClass type, String varName, SymbolTable tbl)552*f1fbf3c2SXin Li     public int recordVariable(CtClass type, String varName, SymbolTable tbl)
553*f1fbf3c2SXin Li         throws CompileError
554*f1fbf3c2SXin Li     {
555*f1fbf3c2SXin Li         if (varName == null)
556*f1fbf3c2SXin Li             return -1;
557*f1fbf3c2SXin Li         int varNo = getMaxLocals();
558*f1fbf3c2SXin Li         int locals = varNo + recordVar(type, varName, varNo, tbl);
559*f1fbf3c2SXin Li         setMaxLocals(locals);
560*f1fbf3c2SXin Li         return varNo;
561*f1fbf3c2SXin Li     }
562*f1fbf3c2SXin Li 
recordVar(CtClass cc, String varName, int varNo, SymbolTable tbl)563*f1fbf3c2SXin Li     private int recordVar(CtClass cc, String varName, int varNo,
564*f1fbf3c2SXin Li                           SymbolTable tbl) throws CompileError
565*f1fbf3c2SXin Li     {
566*f1fbf3c2SXin Li         if (cc == CtClass.voidType) {
567*f1fbf3c2SXin Li             exprType = CLASS;
568*f1fbf3c2SXin Li             arrayDim = 0;
569*f1fbf3c2SXin Li             className = jvmJavaLangObject;
570*f1fbf3c2SXin Li         }
571*f1fbf3c2SXin Li         else
572*f1fbf3c2SXin Li             setType(cc);
573*f1fbf3c2SXin Li 
574*f1fbf3c2SXin Li         Declarator decl
575*f1fbf3c2SXin Li             = new Declarator(exprType, className, arrayDim,
576*f1fbf3c2SXin Li                              varNo, new Symbol(varName));
577*f1fbf3c2SXin Li         tbl.append(varName, decl);
578*f1fbf3c2SXin Li         return is2word(exprType, arrayDim) ? 2 : 1;
579*f1fbf3c2SXin Li     }
580*f1fbf3c2SXin Li 
581*f1fbf3c2SXin Li     /**
582*f1fbf3c2SXin Li      * Makes the given variable name available.
583*f1fbf3c2SXin Li      *
584*f1fbf3c2SXin Li      * @param typeDesc  the type descriptor of the variable
585*f1fbf3c2SXin Li      * @param varName   variable name
586*f1fbf3c2SXin Li      * @param varNo     an index into the local variable array
587*f1fbf3c2SXin Li      */
recordVariable(String typeDesc, String varName, int varNo, SymbolTable tbl)588*f1fbf3c2SXin Li     public void recordVariable(String typeDesc, String varName, int varNo,
589*f1fbf3c2SXin Li                                SymbolTable tbl) throws CompileError
590*f1fbf3c2SXin Li     {
591*f1fbf3c2SXin Li         char c;
592*f1fbf3c2SXin Li         int dim = 0;
593*f1fbf3c2SXin Li         while ((c = typeDesc.charAt(dim)) == '[')
594*f1fbf3c2SXin Li             ++dim;
595*f1fbf3c2SXin Li 
596*f1fbf3c2SXin Li         int type = MemberResolver.descToType(c);
597*f1fbf3c2SXin Li         String cname = null;
598*f1fbf3c2SXin Li         if (type == CLASS) {
599*f1fbf3c2SXin Li             if (dim == 0)
600*f1fbf3c2SXin Li                 cname = typeDesc.substring(1, typeDesc.length() - 1);
601*f1fbf3c2SXin Li             else
602*f1fbf3c2SXin Li                 cname = typeDesc.substring(dim + 1, typeDesc.length() - 1);
603*f1fbf3c2SXin Li         }
604*f1fbf3c2SXin Li 
605*f1fbf3c2SXin Li         Declarator decl
606*f1fbf3c2SXin Li             = new Declarator(type, cname, dim, varNo, new Symbol(varName));
607*f1fbf3c2SXin Li         tbl.append(varName, decl);
608*f1fbf3c2SXin Li     }
609*f1fbf3c2SXin Li 
610*f1fbf3c2SXin Li     /* compileParameterList() returns the stack size used
611*f1fbf3c2SXin Li      * by the produced code.
612*f1fbf3c2SXin Li      *
613*f1fbf3c2SXin Li      * This method correctly computes the max_stack value.
614*f1fbf3c2SXin Li      *
615*f1fbf3c2SXin Li      * @param regno     the index of the local variable in which
616*f1fbf3c2SXin Li      *                  the first argument is received.
617*f1fbf3c2SXin Li      *                  (0: static method, 1: regular method.)
618*f1fbf3c2SXin Li      */
compileParameterList(Bytecode code, CtClass[] params, int regno)619*f1fbf3c2SXin Li     public static int compileParameterList(Bytecode code,
620*f1fbf3c2SXin Li                                 CtClass[] params, int regno) {
621*f1fbf3c2SXin Li         if (params == null) {
622*f1fbf3c2SXin Li             code.addIconst(0);                          // iconst_0
623*f1fbf3c2SXin Li             code.addAnewarray(javaLangObject);          // anewarray Object
624*f1fbf3c2SXin Li             return 1;
625*f1fbf3c2SXin Li         }
626*f1fbf3c2SXin Li         CtClass[] args = new CtClass[1];
627*f1fbf3c2SXin Li         int n = params.length;
628*f1fbf3c2SXin Li         code.addIconst(n);                          // iconst_<n>
629*f1fbf3c2SXin Li         code.addAnewarray(javaLangObject);          // anewarray Object
630*f1fbf3c2SXin Li         for (int i = 0; i < n; ++i) {
631*f1fbf3c2SXin Li             code.addOpcode(Bytecode.DUP);           // dup
632*f1fbf3c2SXin Li             code.addIconst(i);                      // iconst_<i>
633*f1fbf3c2SXin Li             if (params[i].isPrimitive()) {
634*f1fbf3c2SXin Li                 CtPrimitiveType pt = (CtPrimitiveType)params[i];
635*f1fbf3c2SXin Li                 String wrapper = pt.getWrapperName();
636*f1fbf3c2SXin Li                 code.addNew(wrapper);               // new <wrapper>
637*f1fbf3c2SXin Li                 code.addOpcode(Bytecode.DUP);       // dup
638*f1fbf3c2SXin Li                 int s = code.addLoad(regno, pt);    // ?load <regno>
639*f1fbf3c2SXin Li                 regno += s;
640*f1fbf3c2SXin Li                 args[0] = pt;
641*f1fbf3c2SXin Li                 code.addInvokespecial(wrapper, "<init>",
642*f1fbf3c2SXin Li                             Descriptor.ofMethod(CtClass.voidType, args));
643*f1fbf3c2SXin Li                                                     // invokespecial
644*f1fbf3c2SXin Li             }
645*f1fbf3c2SXin Li             else {
646*f1fbf3c2SXin Li                 code.addAload(regno);               // aload <regno>
647*f1fbf3c2SXin Li                 ++regno;
648*f1fbf3c2SXin Li             }
649*f1fbf3c2SXin Li 
650*f1fbf3c2SXin Li             code.addOpcode(Bytecode.AASTORE);       // aastore
651*f1fbf3c2SXin Li         }
652*f1fbf3c2SXin Li 
653*f1fbf3c2SXin Li         return 8;
654*f1fbf3c2SXin Li     }
655*f1fbf3c2SXin Li 
compileUnwrapValue(CtClass type, Bytecode code)656*f1fbf3c2SXin Li     protected void compileUnwrapValue(CtClass type, Bytecode code)
657*f1fbf3c2SXin Li         throws CompileError
658*f1fbf3c2SXin Li     {
659*f1fbf3c2SXin Li         if (type == CtClass.voidType) {
660*f1fbf3c2SXin Li             addNullIfVoid();
661*f1fbf3c2SXin Li             return;
662*f1fbf3c2SXin Li         }
663*f1fbf3c2SXin Li 
664*f1fbf3c2SXin Li         if (exprType == VOID)
665*f1fbf3c2SXin Li             throw new CompileError("invalid type for " + returnCastName);
666*f1fbf3c2SXin Li 
667*f1fbf3c2SXin Li         if (type instanceof CtPrimitiveType) {
668*f1fbf3c2SXin Li             CtPrimitiveType pt = (CtPrimitiveType)type;
669*f1fbf3c2SXin Li             // pt is not voidType.
670*f1fbf3c2SXin Li             String wrapper = pt.getWrapperName();
671*f1fbf3c2SXin Li             code.addCheckcast(wrapper);
672*f1fbf3c2SXin Li             code.addInvokevirtual(wrapper, pt.getGetMethodName(),
673*f1fbf3c2SXin Li                                   pt.getGetMethodDescriptor());
674*f1fbf3c2SXin Li             setType(type);
675*f1fbf3c2SXin Li         }
676*f1fbf3c2SXin Li         else {
677*f1fbf3c2SXin Li             code.addCheckcast(type);
678*f1fbf3c2SXin Li             setType(type);
679*f1fbf3c2SXin Li         }
680*f1fbf3c2SXin Li     }
681*f1fbf3c2SXin Li 
682*f1fbf3c2SXin Li     /* Sets exprType, arrayDim, and className;
683*f1fbf3c2SXin Li      * If type is void, then this method does nothing.
684*f1fbf3c2SXin Li      */
setType(CtClass type)685*f1fbf3c2SXin Li     public void setType(CtClass type) throws CompileError {
686*f1fbf3c2SXin Li         setType(type, 0);
687*f1fbf3c2SXin Li     }
688*f1fbf3c2SXin Li 
setType(CtClass type, int dim)689*f1fbf3c2SXin Li     private void setType(CtClass type, int dim) throws CompileError {
690*f1fbf3c2SXin Li         if (type.isPrimitive()) {
691*f1fbf3c2SXin Li             CtPrimitiveType pt = (CtPrimitiveType)type;
692*f1fbf3c2SXin Li             exprType = MemberResolver.descToType(pt.getDescriptor());
693*f1fbf3c2SXin Li             arrayDim = dim;
694*f1fbf3c2SXin Li             className = null;
695*f1fbf3c2SXin Li         }
696*f1fbf3c2SXin Li         else if (type.isArray())
697*f1fbf3c2SXin Li             try {
698*f1fbf3c2SXin Li                 setType(type.getComponentType(), dim + 1);
699*f1fbf3c2SXin Li             }
700*f1fbf3c2SXin Li             catch (NotFoundException e) {
701*f1fbf3c2SXin Li                 throw new CompileError("undefined type: " + type.getName());
702*f1fbf3c2SXin Li             }
703*f1fbf3c2SXin Li         else {
704*f1fbf3c2SXin Li             exprType = CLASS;
705*f1fbf3c2SXin Li             arrayDim = dim;
706*f1fbf3c2SXin Li             className = MemberResolver.javaToJvmName(type.getName());
707*f1fbf3c2SXin Li         }
708*f1fbf3c2SXin Li     }
709*f1fbf3c2SXin Li 
710*f1fbf3c2SXin Li     /* Performs implicit coercion from exprType to type.
711*f1fbf3c2SXin Li      */
doNumCast(CtClass type)712*f1fbf3c2SXin Li     public void doNumCast(CtClass type) throws CompileError {
713*f1fbf3c2SXin Li         if (arrayDim == 0 && !isRefType(exprType))
714*f1fbf3c2SXin Li             if (type instanceof CtPrimitiveType) {
715*f1fbf3c2SXin Li                 CtPrimitiveType pt = (CtPrimitiveType)type;
716*f1fbf3c2SXin Li                 atNumCastExpr(exprType,
717*f1fbf3c2SXin Li                               MemberResolver.descToType(pt.getDescriptor()));
718*f1fbf3c2SXin Li             }
719*f1fbf3c2SXin Li             else
720*f1fbf3c2SXin Li                 throw new CompileError("type mismatch");
721*f1fbf3c2SXin Li     }
722*f1fbf3c2SXin Li }
723