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