1 package org.apache.bcel.util;
2
3 import org.apache.bcel.generic.*;
4 import org.apache.bcel.classfile.Utility;
5 import org.apache.bcel.Constants;
6 import java.io.PrintWriter;
7 import java.util.*;
8
9 /* ====================================================================
10 * The Apache Software License, Version 1.1
11 *
12 * Copyright (c) 2002 The Apache Software Foundation. All rights
13 * reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 *
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 *
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in
24 * the documentation and/or other materials provided with the
25 * distribution.
26 *
27 * 3. The end-user documentation included with the redistribution,
28 * if any, must include the following acknowledgment:
29 * "This product includes software developed by the
30 * Apache Software Foundation (http://www.apache.org/)."
31 * Alternately, this acknowledgment may appear in the software itself,
32 * if and wherever such third-party acknowledgments normally appear.
33 *
34 * 4. The names "Apache" and "Apache Software Foundation" and
35 * "Apache BCEL" must not be used to endorse or promote products
36 * derived from this software without prior written permission. For
37 * written permission, please contact apache@apache.org.
38 *
39 * 5. Products derived from this software may not be called "Apache",
40 * "Apache BCEL", nor may "Apache" appear in their name, without
41 * prior written permission of the Apache Software Foundation.
42 *
43 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
44 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
45 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
46 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
47 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
50 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
51 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
52 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
53 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 * ====================================================================
56 *
57 * This software consists of voluntary contributions made by many
58 * individuals on behalf of the Apache Software Foundation. For more
59 * information on the Apache Software Foundation, please see
60 * <http://www.apache.org/>.
61 */
62
63 /***
64 * Factory creates il.append() statements, and sets instruction targets.
65 * A helper class for BCELifier.
66 *
67 * @see BCELifier
68 * @version $Id: BCELFactory.java,v 1.3 2002/11/28 07:36:53 mdahm Exp $
69 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
70 */
71 class BCELFactory extends EmptyVisitor {
72 private MethodGen _mg;
73 private PrintWriter _out;
74 private ConstantPoolGen _cp;
75
76 BCELFactory(MethodGen mg, PrintWriter out) {
77 _mg = mg;
78 _cp = mg.getConstantPool();
79 _out = out;
80 }
81
82 private HashMap branch_map = new HashMap(); // Map<Instruction, InstructionHandle>
83
84 public void start() {
85 if(!_mg.isAbstract() && !_mg.isNative()) {
86 for(InstructionHandle ih = _mg.getInstructionList().getStart();
87 ih != null; ih = ih.getNext()) {
88 Instruction i = ih.getInstruction();
89
90 if(i instanceof BranchInstruction) {
91 branch_map.put(i, ih); // memorize container
92 }
93
94 if(ih.hasTargeters()) {
95 if(i instanceof BranchInstruction) {
96 _out.println(" InstructionHandle ih_" + ih.getPosition() + ";");
97 } else {
98 _out.print(" InstructionHandle ih_" + ih.getPosition() + " = ");
99 }
100 } else {
101 _out.print(" ");
102 }
103
104 if(!visitInstruction(i))
105 i.accept(this);
106 }
107
108 updateBranchTargets();
109 updateExceptionHandlers();
110 }
111 }
112
113 private boolean visitInstruction(Instruction i) {
114 short opcode = i.getOpcode();
115
116 if((InstructionConstants.INSTRUCTIONS[opcode] != null) &&
117 !(i instanceof ConstantPushInstruction) &&
118 !(i instanceof ReturnInstruction)) { // Handled below
119 _out.println("il.append(InstructionConstants." +
120 i.getName().toUpperCase() + ");");
121 return true;
122 }
123
124 return false;
125 }
126
127 public void visitLocalVariableInstruction(LocalVariableInstruction i) {
128 short opcode = i.getOpcode();
129 Type type = i.getType(_cp);
130
131 if(opcode == Constants.IINC) {
132 _out.println("il.append(new IINC(" + i.getIndex() + ", " +
133 ((IINC)i).getIncrement() + "));");
134 } else {
135 String kind = (opcode < Constants.ISTORE)? "Load" : "Store";
136 _out.println("il.append(_factory.create" + kind + "(" +
137 BCELifier.printType(type) + ", " +
138 i.getIndex() + "));");
139 }
140 }
141
142 public void visitArrayInstruction(ArrayInstruction i) {
143 short opcode = i.getOpcode();
144 Type type = i.getType(_cp);
145 String kind = (opcode < Constants.IASTORE)? "Load" : "Store";
146
147 _out.println("il.append(_factory.createArray" + kind + "(" +
148 BCELifier.printType(type) + "));");
149 }
150
151 public void visitFieldInstruction(FieldInstruction i) {
152 short opcode = i.getOpcode();
153
154 String class_name = i.getClassName(_cp);
155 String field_name = i.getFieldName(_cp);
156 Type type = i.getFieldType(_cp);
157
158 _out.println("il.append(_factory.createFieldAccess(\"" +
159 class_name + "\", \"" + field_name + "\", " +
160 BCELifier.printType(type) + ", " +
161 "Constants." + Constants.OPCODE_NAMES[opcode].toUpperCase() +
162 "));");
163 }
164
165 public void visitInvokeInstruction(InvokeInstruction i) {
166 short opcode = i.getOpcode();
167 String class_name = i.getClassName(_cp);
168 String method_name = i.getMethodName(_cp);
169 Type type = i.getReturnType(_cp);
170 Type[] arg_types = i.getArgumentTypes(_cp);
171
172 _out.println("il.append(_factory.createInvoke(\"" +
173 class_name + "\", \"" + method_name + "\", " +
174 BCELifier.printType(type) + ", " +
175 BCELifier.printArgumentTypes(arg_types) + ", " +
176 "Constants." + Constants.OPCODE_NAMES[opcode].toUpperCase() +
177 "));");
178 }
179
180 public void visitAllocationInstruction(AllocationInstruction i) {
181 Type type;
182
183 if(i instanceof CPInstruction) {
184 type = ((CPInstruction)i).getType(_cp);
185 } else {
186 type = ((NEWARRAY)i).getType();
187 }
188
189 short opcode = ((Instruction)i).getOpcode();
190 int dim = 1;
191
192 switch(opcode) {
193 case Constants.NEW:
194 _out.println("il.append(_factory.createNew(\"" +
195 ((ObjectType)type).getClassName() + "\"));");
196 break;
197
198 case Constants.MULTIANEWARRAY:
199 dim = ((MULTIANEWARRAY)i).getDimensions();
200
201 case Constants.ANEWARRAY:
202 case Constants.NEWARRAY:
203 _out.println("il.append(_factory.createNewArray(" +
204 BCELifier.printType(type) + ", (short) " + dim + "));");
205 break;
206
207 default:
208 throw new RuntimeException("Oops: " + opcode);
209 }
210 }
211
212 private void createConstant(Object value) {
213 String embed = value.toString();
214
215 if(value instanceof String)
216 embed = '"' + Utility.convertString(value.toString()) + '"';
217 else if(value instanceof Character)
218 embed = "(char)0x" + Integer.toHexString(((Character)value).charValue());
219
220 _out.println("il.append(new PUSH(_cp, " + embed + "));");
221 }
222
223 public void visitLDC(LDC i) {
224 createConstant(i.getValue(_cp));
225 }
226
227 public void visitLDC2_W(LDC2_W i) {
228 createConstant(i.getValue(_cp));
229 }
230
231 public void visitConstantPushInstruction(ConstantPushInstruction i) {
232 createConstant(i.getValue());
233 }
234
235 public void visitINSTANCEOF(INSTANCEOF i) {
236 Type type = i.getType(_cp);
237
238 _out.println("il.append(new INSTANCEOF(_cp.addClass(" +
239 BCELifier.printType(type) + ")));");
240 }
241
242 public void visitCHECKCAST(CHECKCAST i) {
243 Type type = i.getType(_cp);
244
245 _out.println("il.append(_factory.createCheckCast(" +
246 BCELifier.printType(type) + "));");
247 }
248
249 public void visitReturnInstruction(ReturnInstruction i) {
250 Type type = i.getType(_cp);
251
252 _out.println("il.append(_factory.createReturn(" +
253 BCELifier.printType(type) + "));");
254 }
255
256 // Memorize BranchInstructions that need an update
257 private ArrayList branches = new ArrayList();
258
259 public void visitBranchInstruction(BranchInstruction bi) {
260 BranchHandle bh = (BranchHandle)branch_map.get(bi);
261 int pos = bh.getPosition();
262 String name = bi.getName() + "_" + pos;
263
264 if(bi instanceof Select) {
265 Select s = (Select)bi;
266 branches.add(bi);
267
268 StringBuffer args = new StringBuffer("new int[] { ");
269 int[] matchs = s.getMatchs();
270
271 for(int i=0; i < matchs.length; i++) {
272 args.append(matchs[i]);
273
274 if(i < matchs.length - 1)
275 args.append(", ");
276 }
277
278 args.append(" }");
279
280 _out.print(" Select " + name + " = new " +
281 bi.getName().toUpperCase() + "(" + args +
282 ", new InstructionHandle[] { ");
283
284 for(int i=0; i < matchs.length; i++) {
285 _out.print("null");
286
287 if(i < matchs.length - 1)
288 _out.print(", ");
289 }
290
291 _out.println(");");
292 } else {
293 int t_pos = bh.getTarget().getPosition();
294 String target;
295
296 if(pos > t_pos) {
297 target = "ih_" + t_pos;
298 } else {
299 branches.add(bi);
300 target = "null";
301 }
302
303 _out.println(" BranchInstruction " + name +
304 " = _factory.createBranchInstruction(" +
305 "Constants." + bi.getName().toUpperCase() + ", " +
306 target + ");");
307 }
308
309 if(bh.hasTargeters())
310 _out.println(" ih_" + pos + " = il.append(" + name + ");");
311 else
312 _out.println(" il.append(" + name + ");");
313 }
314
315 public void visitRET(RET i) {
316 _out.println("il.append(new RET(" + i.getIndex() + ")));");
317 }
318
319 private void updateBranchTargets() {
320 for(Iterator i = branches.iterator(); i.hasNext(); ) {
321 BranchInstruction bi = (BranchInstruction)i.next();
322 BranchHandle bh = (BranchHandle)branch_map.get(bi);
323 int pos = bh.getPosition();
324 String name = bi.getName() + "_" + pos;
325 int t_pos = bh.getTarget().getPosition();
326
327 _out.println(" " + name + ".setTarget(ih_" + t_pos + ");");
328
329 if(bi instanceof Select) {
330 InstructionHandle[] ihs = ((Select)bi).getTargets();
331
332 for(int j = 0; j < ihs.length; j++) {
333 t_pos = ihs[j].getPosition();
334
335 _out.println(" " + name + ".setTarget(" + j +
336 ", ih_" + t_pos + ");");
337 }
338 }
339 }
340 }
341
342 private void updateExceptionHandlers() {
343 CodeExceptionGen[] handlers = _mg.getExceptionHandlers();
344
345 for(int i=0; i < handlers.length; i++) {
346 CodeExceptionGen h = handlers[i];
347 String type = (h.getCatchType() == null)?
348 "null" : BCELifier.printType(h.getCatchType());
349
350 _out.println(" method.addExceptionHandler(" +
351 "ih_" + h.getStartPC().getPosition() + ", " +
352 "ih_" + h.getEndPC().getPosition() + ", " +
353 "ih_" + h.getHandlerPC().getPosition() + ", " +
354 type + ");");
355 }
356 }
357 }
This page was automatically generated by Maven