1 package org.apache.bcel.generic;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache BCEL" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache BCEL", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56 import org.apache.bcel.Constants;
57
58 /***
59 * Instances of this class may be used, e.g., to generate typed
60 * versions of instructions. Its main purpose is to be used as the
61 * byte code generating backend of a compiler. You can subclass it to
62 * add your own create methods.
63 *
64 * @version $Id: InstructionFactory.java,v 1.6 2002/07/11 19:39:04 mdahm Exp $
65 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
66 * @see Constants
67 */
68 public class InstructionFactory
69 implements InstructionConstants, java.io.Serializable
70 {
71 protected ClassGen cg;
72 protected ConstantPoolGen cp;
73
74 public InstructionFactory(ClassGen cg, ConstantPoolGen cp) {
75 this.cg = cg;
76 this.cp = cp;
77 }
78
79 /*** Initialize with ClassGen object
80 */
81 public InstructionFactory(ClassGen cg) {
82 this(cg, cg.getConstantPool());
83 }
84
85 /*** Initialize just with ConstantPoolGen object
86 */
87 public InstructionFactory(ConstantPoolGen cp) {
88 this(null, cp);
89 }
90
91 /*** Create an invoke instruction.
92 *
93 * @param class_name name of the called class
94 * @param name name of the called method
95 * @param ret_type return type of method
96 * @param arg_types argument types of method
97 * @param kind how to invoke, i.e., INVOKEINTERFACE, INVOKESTATIC, INVOKEVIRTUAL,
98 * or INVOKESPECIAL
99 * @see Constants
100 */
101 public InvokeInstruction createInvoke(String class_name, String name, Type ret_type,
102 Type[] arg_types, short kind) {
103 int index;
104 int nargs = 0;
105 String signature = Type.getMethodSignature(ret_type, arg_types);
106
107 for(int i=0; i < arg_types.length; i++) // Count size of arguments
108 nargs += arg_types[i].getSize();
109
110 if(kind == Constants.INVOKEINTERFACE)
111 index = cp.addInterfaceMethodref(class_name, name, signature);
112 else
113 index = cp.addMethodref(class_name, name, signature);
114
115 switch(kind) {
116 case Constants.INVOKESPECIAL: return new INVOKESPECIAL(index);
117 case Constants.INVOKEVIRTUAL: return new INVOKEVIRTUAL(index);
118 case Constants.INVOKESTATIC: return new INVOKESTATIC(index);
119 case Constants.INVOKEINTERFACE: return new INVOKEINTERFACE(index, nargs + 1);
120 default:
121 throw new RuntimeException("Oops: Unknown invoke kind:" + kind);
122 }
123 }
124
125 /*** Create a call to the most popular System.out.println() method.
126 *
127 * @param s the string to print
128 */
129 public InstructionList createPrintln(String s) {
130 InstructionList il = new InstructionList();
131 int out = cp.addFieldref("java.lang.System", "out",
132 "Ljava/io/PrintStream;");
133 int println = cp.addMethodref("java.io.PrintStream", "println",
134 "(Ljava/lang/String;)V");
135
136 il.append(new GETSTATIC(out));
137 il.append(new PUSH(cp, s));
138 il.append(new INVOKEVIRTUAL(println));
139
140 return il;
141 }
142
143 /*** Uses PUSH to push a constant value onto the stack.
144 * @param value must be of type Number, Boolean, Character or String
145 */
146 public Instruction createConstant(Object value) {
147 PUSH push;
148
149 if(value instanceof Number)
150 push = new PUSH(cp, (Number)value);
151 else if(value instanceof String)
152 push = new PUSH(cp, (String)value);
153 else if(value instanceof Boolean)
154 push = new PUSH(cp, (Boolean)value);
155 else if(value instanceof Character)
156 push = new PUSH(cp, (Character)value);
157 else
158 throw new ClassGenException("Illegal type: " + value.getClass());
159
160 return push.getInstruction();
161 }
162
163 private static class MethodObject {
164 Type[] arg_types;
165 Type result_type;
166 String[] arg_names;
167 String class_name;
168 String name;
169 int access;
170
171 MethodObject(String c, String n, Type r, Type[] a, int acc) {
172 class_name = c;
173 name = n;
174 result_type = r;
175 arg_types = a;
176 access = acc;
177 }
178 }
179
180 private InvokeInstruction createInvoke(MethodObject m, short kind) {
181 return createInvoke(m.class_name, m.name, m.result_type, m.arg_types, kind);
182 }
183
184 private static MethodObject[] append_mos = {
185 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
186 new Type[] { Type.STRING }, Constants.ACC_PUBLIC),
187 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
188 new Type[] { Type.OBJECT }, Constants.ACC_PUBLIC),
189 null, null, // indices 2, 3
190 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
191 new Type[] { Type.BOOLEAN }, Constants.ACC_PUBLIC),
192 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
193 new Type[] { Type.CHAR }, Constants.ACC_PUBLIC),
194 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
195 new Type[] { Type.FLOAT }, Constants.ACC_PUBLIC),
196 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
197 new Type[] { Type.DOUBLE }, Constants.ACC_PUBLIC),
198 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
199 new Type[] { Type.INT }, Constants.ACC_PUBLIC),
200 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(byte)
201 new Type[] { Type.INT }, Constants.ACC_PUBLIC),
202 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER, // No append(short)
203 new Type[] { Type.INT }, Constants.ACC_PUBLIC),
204 new MethodObject("java.lang.StringBuffer", "append", Type.STRINGBUFFER,
205 new Type[] { Type.LONG }, Constants.ACC_PUBLIC)
206 };
207
208 private static final boolean isString(Type type) {
209 return ((type instanceof ObjectType) &&
210 ((ObjectType)type).getClassName().equals("java.lang.String"));
211 }
212
213 public Instruction createAppend(Type type) {
214 byte t = type.getType();
215
216 if(isString(type))
217 return createInvoke(append_mos[0], Constants.INVOKEVIRTUAL);
218
219 switch(t) {
220 case Constants.T_BOOLEAN:
221 case Constants.T_CHAR:
222 case Constants.T_FLOAT:
223 case Constants.T_DOUBLE:
224 case Constants.T_BYTE:
225 case Constants.T_SHORT:
226 case Constants.T_INT:
227 case Constants.T_LONG
228 : return createInvoke(append_mos[t], Constants.INVOKEVIRTUAL);
229 case Constants.T_ARRAY:
230 case Constants.T_OBJECT:
231 return createInvoke(append_mos[1], Constants.INVOKEVIRTUAL);
232 default:
233 throw new RuntimeException("Oops: No append for this type? " + type);
234 }
235 }
236
237 /*** Create a field instruction.
238 *
239 * @param class_name name of the accessed class
240 * @param name name of the referenced field
241 * @param type type of field
242 * @param kind how to access, i.e., GETFIELD, PUTFIELD, GETSTATIC, PUTSTATIC
243 * @see Constants
244 */
245 public FieldInstruction createFieldAccess(String class_name, String name, Type type, short kind) {
246 int index;
247 String signature = type.getSignature();
248
249 index = cp.addFieldref(class_name, name, signature);
250
251 switch(kind) {
252 case Constants.GETFIELD: return new GETFIELD(index);
253 case Constants.PUTFIELD: return new PUTFIELD(index);
254 case Constants.GETSTATIC: return new GETSTATIC(index);
255 case Constants.PUTSTATIC: return new PUTSTATIC(index);
256
257 default:
258 throw new RuntimeException("Oops: Unknown getfield kind:" + kind);
259 }
260 }
261
262 /*** Create reference to `this'
263 */
264 public static Instruction createThis() {
265 return new ALOAD(0);
266 }
267
268 /*** Create typed return
269 */
270 public static ReturnInstruction createReturn(Type type) {
271 switch(type.getType()) {
272 case Constants.T_ARRAY:
273 case Constants.T_OBJECT: return ARETURN;
274 case Constants.T_INT:
275 case Constants.T_SHORT:
276 case Constants.T_BOOLEAN:
277 case Constants.T_CHAR:
278 case Constants.T_BYTE: return IRETURN;
279 case Constants.T_FLOAT: return FRETURN;
280 case Constants.T_DOUBLE: return DRETURN;
281 case Constants.T_LONG: return LRETURN;
282 case Constants.T_VOID: return RETURN;
283
284 default:
285 throw new RuntimeException("Invalid type: " + type);
286 }
287 }
288
289 private static final ArithmeticInstruction createBinaryIntOp(char first, String op) {
290 switch(first) {
291 case '-' : return ISUB;
292 case '+' : return IADD;
293 case '%' : return IREM;
294 case '*' : return IMUL;
295 case '/' : return IDIV;
296 case '&' : return IAND;
297 case '|' : return IOR;
298 case '^' : return IXOR;
299 case '<' : return ISHL;
300 case '>' : return op.equals(">>>")? (ArithmeticInstruction)IUSHR :
301 (ArithmeticInstruction)ISHR;
302 default: throw new RuntimeException("Invalid operand " + op);
303 }
304 }
305
306 private static final ArithmeticInstruction createBinaryLongOp(char first, String op) {
307 switch(first) {
308 case '-' : return LSUB;
309 case '+' : return LADD;
310 case '%' : return LREM;
311 case '*' : return LMUL;
312 case '/' : return LDIV;
313 case '&' : return LAND;
314 case '|' : return LOR;
315 case '^' : return LXOR;
316 case '<' : return LSHL;
317 case '>' : return op.equals(">>>")? (ArithmeticInstruction)LUSHR :
318 (ArithmeticInstruction)LSHR;
319 default: throw new RuntimeException("Invalid operand " + op);
320 }
321 }
322
323 private static final ArithmeticInstruction createBinaryFloatOp(char op) {
324 switch(op) {
325 case '-' : return FSUB;
326 case '+' : return FADD;
327 case '*' : return FMUL;
328 case '/' : return FDIV;
329 default: throw new RuntimeException("Invalid operand " + op);
330 }
331 }
332
333 private static final ArithmeticInstruction createBinaryDoubleOp(char op) {
334 switch(op) {
335 case '-' : return DSUB;
336 case '+' : return DADD;
337 case '*' : return DMUL;
338 case '/' : return DDIV;
339 default: throw new RuntimeException("Invalid operand " + op);
340 }
341 }
342
343 /***
344 * Create binary operation for simple basic types, such as int and float.
345 *
346 * @param op operation, such as "+", "*", "<<", etc.
347 */
348 public static ArithmeticInstruction createBinaryOperation(String op, Type type) {
349 char first = op.toCharArray()[0];
350
351 switch(type.getType()) {
352 case Constants.T_BYTE:
353 case Constants.T_SHORT:
354 case Constants.T_INT:
355 case Constants.T_CHAR: return createBinaryIntOp(first, op);
356 case Constants.T_LONG: return createBinaryLongOp(first, op);
357 case Constants.T_FLOAT: return createBinaryFloatOp(first);
358 case Constants.T_DOUBLE: return createBinaryDoubleOp(first);
359 default: throw new RuntimeException("Invalid type " + type);
360 }
361 }
362
363 /***
364 * @param size size of operand, either 1 (int, e.g.) or 2 (double)
365 */
366 public static StackInstruction createPop(int size) {
367 return (size == 2)? (StackInstruction)POP2 :
368 (StackInstruction)POP;
369 }
370
371 /***
372 * @param size size of operand, either 1 (int, e.g.) or 2 (double)
373 */
374 public static StackInstruction createDup(int size) {
375 return (size == 2)? (StackInstruction)DUP2 :
376 (StackInstruction)DUP;
377 }
378
379 /***
380 * @param size size of operand, either 1 (int, e.g.) or 2 (double)
381 */
382 public static StackInstruction createDup_2(int size) {
383 return (size == 2)? (StackInstruction)DUP2_X2 :
384 (StackInstruction)DUP_X2;
385 }
386
387 /***
388 * @param size size of operand, either 1 (int, e.g.) or 2 (double)
389 */
390 public static StackInstruction createDup_1(int size) {
391 return (size == 2)? (StackInstruction)DUP2_X1 :
392 (StackInstruction)DUP_X1;
393 }
394
395 /***
396 * @param index index of local variable
397 */
398 public static LocalVariableInstruction createStore(Type type, int index) {
399 switch(type.getType()) {
400 case Constants.T_BOOLEAN:
401 case Constants.T_CHAR:
402 case Constants.T_BYTE:
403 case Constants.T_SHORT:
404 case Constants.T_INT: return new ISTORE(index);
405 case Constants.T_FLOAT: return new FSTORE(index);
406 case Constants.T_DOUBLE: return new DSTORE(index);
407 case Constants.T_LONG: return new LSTORE(index);
408 case Constants.T_ARRAY:
409 case Constants.T_OBJECT: return new ASTORE(index);
410 default: throw new RuntimeException("Invalid type " + type);
411 }
412 }
413
414 /***
415 * @param index index of local variable
416 */
417 public static LocalVariableInstruction createLoad(Type type, int index) {
418 switch(type.getType()) {
419 case Constants.T_BOOLEAN:
420 case Constants.T_CHAR:
421 case Constants.T_BYTE:
422 case Constants.T_SHORT:
423 case Constants.T_INT: return new ILOAD(index);
424 case Constants.T_FLOAT: return new FLOAD(index);
425 case Constants.T_DOUBLE: return new DLOAD(index);
426 case Constants.T_LONG: return new LLOAD(index);
427 case Constants.T_ARRAY:
428 case Constants.T_OBJECT: return new ALOAD(index);
429 default: throw new RuntimeException("Invalid type " + type);
430 }
431 }
432
433 /***
434 * @param type type of elements of array, i.e., array.getElementType()
435 */
436 public static ArrayInstruction createArrayLoad(Type type) {
437 switch(type.getType()) {
438 case Constants.T_BOOLEAN:
439 case Constants.T_BYTE: return BALOAD;
440 case Constants.T_CHAR: return CALOAD;
441 case Constants.T_SHORT: return SALOAD;
442 case Constants.T_INT: return IALOAD;
443 case Constants.T_FLOAT: return FALOAD;
444 case Constants.T_DOUBLE: return DALOAD;
445 case Constants.T_LONG: return LALOAD;
446 case Constants.T_ARRAY:
447 case Constants.T_OBJECT: return AALOAD;
448 default: throw new RuntimeException("Invalid type " + type);
449 }
450 }
451
452 /***
453 * @param type type of elements of array, i.e., array.getElementType()
454 */
455 public static ArrayInstruction createArrayStore(Type type) {
456 switch(type.getType()) {
457 case Constants.T_BOOLEAN:
458 case Constants.T_BYTE: return BASTORE;
459 case Constants.T_CHAR: return CASTORE;
460 case Constants.T_SHORT: return SASTORE;
461 case Constants.T_INT: return IASTORE;
462 case Constants.T_FLOAT: return FASTORE;
463 case Constants.T_DOUBLE: return DASTORE;
464 case Constants.T_LONG: return LASTORE;
465 case Constants.T_ARRAY:
466 case Constants.T_OBJECT: return AASTORE;
467 default: throw new RuntimeException("Invalid type " + type);
468 }
469 }
470
471
472 /*** Create conversion operation for two stack operands, this may be an I2C, instruction, e.g.,
473 * if the operands are basic types and CHECKCAST if they are reference types.
474 */
475 public Instruction createCast(Type src_type, Type dest_type) {
476 if((src_type instanceof BasicType) && (dest_type instanceof BasicType)) {
477 byte dest = dest_type.getType();
478 byte src = src_type.getType();
479
480 if(dest == Constants.T_LONG && (src == Constants.T_CHAR || src == Constants.T_BYTE ||
481 src == Constants.T_SHORT))
482 src = Constants.T_INT;
483
484 String[] short_names = { "C", "F", "D", "B", "S", "I", "L" };
485
486 String name = "org.apache.bcel.generic." + short_names[src - Constants.T_CHAR] +
487 "2" + short_names[dest - Constants.T_CHAR];
488
489 Instruction i = null;
490 try {
491 i = (Instruction)java.lang.Class.forName(name).newInstance();
492 } catch(Exception e) {
493 throw new RuntimeException("Could not find instruction: " + name);
494 }
495
496 return i;
497 } else if((src_type instanceof ReferenceType) && (dest_type instanceof ReferenceType)) {
498 if(dest_type instanceof ArrayType)
499 return new CHECKCAST(cp.addArrayClass((ArrayType)dest_type));
500 else
501 return new CHECKCAST(cp.addClass(((ObjectType)dest_type).getClassName()));
502 }
503 else
504 throw new RuntimeException("Can not cast " + src_type + " to " + dest_type);
505 }
506
507 public GETFIELD createGetField(String class_name, String name, Type t) {
508 return new GETFIELD(cp.addFieldref(class_name, name, t.getSignature()));
509 }
510
511 public GETSTATIC createGetStatic(String class_name, String name, Type t) {
512 return new GETSTATIC(cp.addFieldref(class_name, name, t.getSignature()));
513 }
514
515 public PUTFIELD createPutField(String class_name, String name, Type t) {
516 return new PUTFIELD(cp.addFieldref(class_name, name, t.getSignature()));
517 }
518
519 public PUTSTATIC createPutStatic(String class_name, String name, Type t) {
520 return new PUTSTATIC(cp.addFieldref(class_name, name, t.getSignature()));
521 }
522
523 public CHECKCAST createCheckCast(ReferenceType t) {
524 if(t instanceof ArrayType)
525 return new CHECKCAST(cp.addArrayClass((ArrayType)t));
526 else
527 return new CHECKCAST(cp.addClass((ObjectType)t));
528 }
529
530 public INSTANCEOF createInstanceOf(ReferenceType t) {
531 if(t instanceof ArrayType)
532 return new INSTANCEOF(cp.addArrayClass((ArrayType)t));
533 else
534 return new INSTANCEOF(cp.addClass((ObjectType)t));
535 }
536
537 public NEW createNew(ObjectType t) {
538 return new NEW(cp.addClass(t));
539 }
540
541 public NEW createNew(String s) {
542 return createNew(new ObjectType(s));
543 }
544
545 /*** Create new array of given size and type.
546 * @return an instruction that creates the corresponding array at runtime, i.e. is an AllocationInstruction
547 */
548 public Instruction createNewArray(Type t, short dim) {
549 if(dim == 1) {
550 if(t instanceof ObjectType)
551 return new ANEWARRAY(cp.addClass((ObjectType)t));
552 else if(t instanceof ArrayType)
553 return new ANEWARRAY(cp.addArrayClass((ArrayType)t));
554 else
555 return new NEWARRAY(((BasicType)t).getType());
556 } else {
557 ArrayType at;
558
559 if(t instanceof ArrayType)
560 at = (ArrayType)t;
561 else
562 at = new ArrayType(t, dim);
563
564 return new MULTIANEWARRAY(cp.addArrayClass(at), dim);
565 }
566 }
567
568 /*** Create "null" value for reference types, 0 for basic types like int
569 */
570 public static Instruction createNull(Type type) {
571 switch(type.getType()) {
572 case Constants.T_ARRAY:
573 case Constants.T_OBJECT: return ACONST_NULL;
574 case Constants.T_INT:
575 case Constants.T_SHORT:
576 case Constants.T_BOOLEAN:
577 case Constants.T_CHAR:
578 case Constants.T_BYTE: return ICONST_0;
579 case Constants.T_FLOAT: return FCONST_0;
580 case Constants.T_DOUBLE: return DCONST_0;
581 case Constants.T_LONG: return LCONST_0;
582 case Constants.T_VOID: return NOP;
583
584 default:
585 throw new RuntimeException("Invalid type: " + type);
586 }
587 }
588
589 /*** Create branch instruction by given opcode, except LOOKUPSWITCH and TABLESWITCH.
590 * For those you should use the SWITCH compound instruction.
591 */
592 public static BranchInstruction createBranchInstruction(short opcode, InstructionHandle target) {
593 switch(opcode) {
594 case Constants.IFEQ: return new IFEQ(target);
595 case Constants.IFNE: return new IFNE(target);
596 case Constants.IFLT: return new IFLT(target);
597 case Constants.IFGE: return new IFGE(target);
598 case Constants.IFGT: return new IFGT(target);
599 case Constants.IFLE: return new IFLE(target);
600 case Constants.IF_ICMPEQ: return new IF_ICMPEQ(target);
601 case Constants.IF_ICMPNE: return new IF_ICMPNE(target);
602 case Constants.IF_ICMPLT: return new IF_ICMPLT(target);
603 case Constants.IF_ICMPGE: return new IF_ICMPGE(target);
604 case Constants.IF_ICMPGT: return new IF_ICMPGT(target);
605 case Constants.IF_ICMPLE: return new IF_ICMPLE(target);
606 case Constants.IF_ACMPEQ: return new IF_ACMPEQ(target);
607 case Constants.IF_ACMPNE: return new IF_ACMPNE(target);
608 case Constants.GOTO: return new GOTO(target);
609 case Constants.JSR: return new JSR(target);
610 case Constants.IFNULL: return new IFNULL(target);
611 case Constants.IFNONNULL: return new IFNONNULL(target);
612 case Constants.GOTO_W: return new GOTO_W(target);
613 case Constants.JSR_W: return new JSR_W(target);
614 default:
615 throw new RuntimeException("Invalid opcode: " + opcode);
616 }
617 }
618
619 public void setClassGen(ClassGen c) { cg = c; }
620 public ClassGen getClassGen() { return cg; }
621 public void setConstantPool(ConstantPoolGen c) { cp = c; }
622 public ConstantPoolGen getConstantPool() { return cp; }
623 }
This page was automatically generated by Maven