    View Javadoc
    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