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