1 /*** 2 * ASM: a very small and fast Java bytecode manipulation framework 3 * Copyright (c) 2000-2005 INRIA, France Telecom 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the copyright holders nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package org.objectweb.asm.util; 31 32 import java.util.HashMap; 33 34 import org.objectweb.asm.AnnotationVisitor; 35 import org.objectweb.asm.Handle; 36 import org.objectweb.asm.Label; 37 import org.objectweb.asm.MethodVisitor; 38 import org.objectweb.asm.Opcodes; 39 import org.objectweb.asm.TypePath; 40 41 /** 42 * A {@link MethodVisitor} that prints the ASM code that generates the methods 43 * it visits. 44 * 45 * @author Eric Bruneton 46 * @author Eugene Kuleshov 47 */ 48 public class ASMifierMethodVisitor extends ASMifierAbstractVisitor implements 49 MethodVisitor 50 { 51 /** 52 * Constructs a new {@link ASMifierMethodVisitor} object. 53 */ 54 public ASMifierMethodVisitor() { 55 super("mv"); 56 this.labelNames = new HashMap(); 57 } 58 59 @Override 60 public AnnotationVisitor visitAnnotationDefault() { 61 buf.setLength(0); 62 buf.append("{\n").append("av0 = mv.visitAnnotationDefault();\n"); 63 text.add(buf.toString()); 64 ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0); 65 text.add(av.getText()); 66 text.add("}\n"); 67 return av; 68 } 69 70 @Override 71 public AnnotationVisitor visitParameterAnnotation( 72 final int parameter, 73 final String desc, 74 final boolean visible) 75 { 76 buf.setLength(0); 77 buf.append("{\n") 78 .append("av0 = mv.visitParameterAnnotation(") 79 .append(parameter) 80 .append(", "); 81 appendConstant(desc); 82 buf.append(", ").append(visible).append(");\n"); 83 text.add(buf.toString()); 84 ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0); 85 text.add(av.getText()); 86 text.add("}\n"); 87 return av; 88 } 89 90 @Override 91 public void visitCode() { 92 text.add("mv.visitCode();\n"); 93 } 94 95 @Override 96 public void visitInsn(final int opcode) { 97 buf.setLength(0); 98 buf.append("mv.visitInsn(").append(OPCODES[opcode]).append(");\n"); 99 text.add(buf.toString()); 100 } 101 102 @Override 103 public void visitIntInsn(final int opcode, final int operand) { 104 buf.setLength(0); 105 buf.append("mv.visitIntInsn(") 106 .append(OPCODES[opcode]) 107 .append(", ") 108 .append(opcode == Opcodes.NEWARRAY 109 ? TYPES[operand] 110 : Integer.toString(operand)) 111 .append(");\n"); 112 text.add(buf.toString()); 113 } 114 115 @Override 116 public void visitVarInsn(final int opcode, final int var) { 117 buf.setLength(0); 118 buf.append("mv.visitVarInsn(") 119 .append(OPCODES[opcode]) 120 .append(", ") 121 .append(var) 122 .append(");\n"); 123 text.add(buf.toString()); 124 } 125 126 @Override 127 public void visitTypeInsn(final int opcode, final String desc) { 128 buf.setLength(0); 129 buf.append("mv.visitTypeInsn(").append(OPCODES[opcode]).append(", "); 130 appendConstant(desc); 131 buf.append(");\n"); 132 text.add(buf.toString()); 133 } 134 135 @Override 136 public void visitFieldInsn( 137 final int opcode, 138 final String owner, 139 final String name, 140 final String desc) 141 { 142 buf.setLength(0); 143 buf.append("mv.visitFieldInsn(").append(OPCODES[opcode]).append(", "); 144 appendConstant(owner); 145 buf.append(", "); 146 appendConstant(name); 147 buf.append(", "); 148 appendConstant(desc); 149 buf.append(");\n"); 150 text.add(buf.toString()); 151 } 152 153 @Override 154 public void visitMethodInsn( 155 final int opcode, 156 final String owner, 157 final String name, 158 final String desc) 159 { 160 buf.setLength(0); 161 buf.append("mv.visitMethodInsn(").append(OPCODES[opcode]).append(", "); 162 appendConstant(owner); 163 buf.append(", "); 164 appendConstant(name); 165 buf.append(", "); 166 appendConstant(desc); 167 buf.append(");\n"); 168 text.add(buf.toString()); 169 } 170 171 @Override 172 public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, 173 Object... bsmArgs) { 174 // TODO Auto-generated method stub 175 176 } 177 178 @Override 179 public AnnotationVisitor visitInsnAnnotation(int typeRef, 180 TypePath typePath, String desc, boolean visible) { 181 // TODO Auto-generated method stub 182 return null; 183 } 184 185 @Override 186 public void visitJumpInsn(final int opcode, final Label label) { 187 buf.setLength(0); 188 declareLabel(label); 189 buf.append("mv.visitJumpInsn(").append(OPCODES[opcode]).append(", "); 190 appendLabel(label); 191 buf.append(");\n"); 192 text.add(buf.toString()); 193 } 194 195 @Override 196 public void visitLabel(final Label label) { 197 buf.setLength(0); 198 declareLabel(label); 199 buf.append("mv.visitLabel("); 200 appendLabel(label); 201 buf.append(");\n"); 202 text.add(buf.toString()); 203 } 204 205 @Override 206 public void visitLdcInsn(final Object cst) { 207 buf.setLength(0); 208 buf.append("mv.visitLdcInsn("); 209 appendConstant(cst); 210 buf.append(");\n"); 211 text.add(buf.toString()); 212 } 213 214 @Override 215 public void visitIincInsn(final int var, final int increment) { 216 buf.setLength(0); 217 buf.append("mv.visitIincInsn(") 218 .append(var) 219 .append(", ") 220 .append(increment) 221 .append(");\n"); 222 text.add(buf.toString()); 223 } 224 225 @Override 226 public void visitTableSwitchInsn( 227 final int min, 228 final int max, 229 final Label dflt, 230 final Label labels[]) 231 { 232 buf.setLength(0); 233 for (int i = 0; i < labels.length; ++i) { 234 declareLabel(labels[i]); 235 } 236 declareLabel(dflt); 237 238 buf.append("mv.visitTableSwitchInsn(") 239 .append(min) 240 .append(", ") 241 .append(max) 242 .append(", "); 243 appendLabel(dflt); 244 buf.append(", new Label[] {"); 245 for (int i = 0; i < labels.length; ++i) { 246 buf.append(i == 0 ? " " : ", "); 247 appendLabel(labels[i]); 248 } 249 buf.append(" });\n"); 250 text.add(buf.toString()); 251 } 252 253 @Override 254 public void visitLookupSwitchInsn( 255 final Label dflt, 256 final int keys[], 257 final Label labels[]) 258 { 259 buf.setLength(0); 260 for (int i = 0; i < labels.length; ++i) { 261 declareLabel(labels[i]); 262 } 263 declareLabel(dflt); 264 265 buf.append("mv.visitLookupSwitchInsn("); 266 appendLabel(dflt); 267 buf.append(", new int[] {"); 268 for (int i = 0; i < keys.length; ++i) { 269 buf.append(i == 0 ? " " : ", ").append(keys[i]); 270 } 271 buf.append(" }, new Label[] {"); 272 for (int i = 0; i < labels.length; ++i) { 273 buf.append(i == 0 ? " " : ", "); 274 appendLabel(labels[i]); 275 } 276 buf.append(" });\n"); 277 text.add(buf.toString()); 278 } 279 280 @Override 281 public void visitMultiANewArrayInsn(final String desc, final int dims) { 282 buf.setLength(0); 283 buf.append("mv.visitMultiANewArrayInsn("); 284 appendConstant(desc); 285 buf.append(", ").append(dims).append(");\n"); 286 text.add(buf.toString()); 287 } 288 289 @Override 290 public void visitTryCatchBlock( 291 final Label start, 292 final Label end, 293 final Label handler, 294 final String type) 295 { 296 buf.setLength(0); 297 declareLabel(start); 298 declareLabel(end); 299 declareLabel(handler); 300 buf.append("mv.visitTryCatchBlock("); 301 appendLabel(start); 302 buf.append(", "); 303 appendLabel(end); 304 buf.append(", "); 305 appendLabel(handler); 306 buf.append(", "); 307 appendConstant(type); 308 buf.append(");\n"); 309 text.add(buf.toString()); 310 } 311 312 @Override 313 public void visitLocalVariable( 314 final String name, 315 final String desc, 316 final String signature, 317 final Label start, 318 final Label end, 319 final int index) 320 { 321 buf.setLength(0); 322 buf.append("mv.visitLocalVariable("); 323 appendConstant(name); 324 buf.append(", "); 325 appendConstant(desc); 326 buf.append(", "); 327 appendConstant(signature); 328 buf.append(", "); 329 appendLabel(start); 330 buf.append(", "); 331 appendLabel(end); 332 buf.append(", ").append(index).append(");\n"); 333 text.add(buf.toString()); 334 } 335 336 @Override 337 public void visitLineNumber(final int line, final Label start) { 338 buf.setLength(0); 339 buf.append("mv.visitLineNumber(").append(line).append(", "); 340 appendLabel(start); 341 buf.append(");\n"); 342 text.add(buf.toString()); 343 } 344 345 @Override 346 public void visitMaxs(final int maxStack, final int maxLocals) { 347 buf.setLength(0); 348 buf.append("mv.visitMaxs(") 349 .append(maxStack) 350 .append(", ") 351 .append(maxLocals) 352 .append(");\n"); 353 text.add(buf.toString()); 354 } 355 356 /** 357 * Appends a declaration of the given label to {@link #buf buf}. This 358 * declaration is of the form "Label lXXX = new Label();". Does nothing if 359 * the given label has already been declared. 360 * 361 * @param l a label. 362 */ 363 private void declareLabel(final Label l) { 364 String name = (String) labelNames.get(l); 365 if (name == null) { 366 name = "l" + labelNames.size(); 367 labelNames.put(l, name); 368 buf.append("Label ").append(name).append(" = new Label();\n"); 369 } 370 } 371 372 /** 373 * Appends the name of the given label to {@link #buf buf}. The given label 374 * <i>must</i> already have a name. One way to ensure this is to always 375 * call {@link #declareLabel declared} before calling this method. 376 * 377 * @param l a label. 378 */ 379 private void appendLabel(final Label l) { 380 buf.append((String) labelNames.get(l)); 381 } 382 } 383