All Downloads are FREE. Search and download functionalities are using the official Maven repository.

proguard.classfile.editor.CompactCodeAttributeComposer Maven / Gradle / Ivy

Go to download

ProGuardCORE is a free library to read, analyze, modify, and write Java class files.

There is a newer version: 9.1.6
Show newest version
/*
 * ProGuardCORE -- library to process Java bytecode.
 *
 * Copyright (c) 2002-2020 Guardsquare NV
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package proguard.classfile.editor;

import static proguard.classfile.ClassConstants.*;

import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.constant.Constant;
import proguard.classfile.instruction.*;
import proguard.classfile.util.*;
import proguard.classfile.visitor.ClassPrinter;
import proguard.resources.file.ResourceFile;

/**
 * This {@link AttributeVisitor} accumulates instructions, exceptions and line numbers, in a compact
 * and fluent style, and then adds them to a method or copies them into code attributes that it
 * visits.
 *
 * 

The class supports composing instructions ({@link #appendInstruction(Instruction)}), labels * ({@link #createLabel()} and {@link #label(Label)}), exception handlers ({@link #catch_(Label, * Label, String, Clazz)}), and line numbers ({@link #line(int)}). * *

The labels are numeric labels that you can choose freely, for example instruction offsets from * existing code that you are copying. You can then refer to them in branches and exception * handlers. You can compose the code as a hierarchy of code fragments with their own local labels. * *

You should provide an estimated maximum size (expressed in number of bytes in the bytecode), * so the implementation can efficiently allocate the necessary internal buffers without * reallocating them as the code grows. * *

For example: * *

 *     ProgramClass  programClass  = ...
 *     ProgramMethod programMethod = ...
 *
 *     // Compose the code.
 *     CompactCodeAttributeComposer composer =
 *         new CompactCodeAttributeComposer(programClass);
 *
 *     final Label TRY_START = composer.createLabel();
 *     final Label TRY_END   = composer.createLabel();
 *     final Label ELSE      = composer.createLabel();
 *
 *     composer
 *         .beginCodeFragment(50)
 *         .label(TRY_START)
 *         .iconst_1()
 *         .iconst_2()
 *         .ificmplt(ELSE)
 *
 *         .iconst_1()
 *         .ireturn()
 *
 *         .label(ELSE)
 *         .iconst_2()
 *         .ireturn()
 *         .label(TRY_END)
 *
 *         .catch_(TRY_START, TRY_END, "java/lang/Exception", null)
 *         .iconst_m1()
 *         .ireturn()
 *         .endCodeFragment();
 *
 *      // Add the code as a code attribute to the given method.
 *      composer.addCodeAttribute(programClass, programMethod);
 * 
* *

This class is mostly convenient to compose code programmatically from scratch. To compose code * based on existing code, where the instructions are already available, see {@link * CodeAttributeComposer}. * *

If you're building many method bodies, it is more efficient to reuse a single instance of this * composer for all methods that you add. * * @author Eric Lafortune */ public class CompactCodeAttributeComposer implements AttributeVisitor { private final ConstantPoolEditor constantPoolEditor; private final CodeAttributeComposer codeAttributeComposer; private int labelCount = 0; /** * Creates a new CompactCodeAttributeComposer that doesn't allow external branch targets or * exception offsets and that automatically shrinks instructions. * * @param targetClass the class to be edited. */ public CompactCodeAttributeComposer(ProgramClass targetClass) { this(targetClass, null, null); } /** * Creates a new CompactCodeAttributeComposer that doesn't allow external branch targets or * exception handlers and that automatically shrinks instructions. * * @param targetClass the class to be edited. * @param programClassPool the program class pool from which new constants can be initialized. * @param libraryClassPool the library class pool from which new constants can be initialized. */ public CompactCodeAttributeComposer( ProgramClass targetClass, ClassPool programClassPool, ClassPool libraryClassPool) { this(targetClass, false, true, true, programClassPool, libraryClassPool); } /** * Creates a new CompactCodeAttributeComposer. * * @param targetClass the class to be edited. * @param allowExternalBranchTargets specifies whether branch targets can lie outside the code * fragment of the branch instructions. * @param allowExternalExceptionOffsets specifies whether exception offsets can lie outside the * code fragment in which exceptions are defined. * @param shrinkInstructions specifies whether instructions should automatically be shrunk before * being written. */ public CompactCodeAttributeComposer( ProgramClass targetClass, boolean allowExternalBranchTargets, boolean allowExternalExceptionOffsets, boolean shrinkInstructions) { this( targetClass, allowExternalBranchTargets, allowExternalExceptionOffsets, shrinkInstructions, null, null); } /** * Creates a new CompactCodeAttributeComposer. * * @param targetClass the class to be edited. * @param allowExternalBranchTargets specifies whether branch targets can lie outside the code * fragment of the branch instructions. * @param allowExternalExceptionOffsets specifies whether exception offsets can lie outside the * code fragment in which exceptions are defined. * @param shrinkInstructions specifies whether instructions should automatically be shrunk before * being written. * @param programClassPool the program class pool from which new constants can be initialized. * @param libraryClassPool the library class pool from which new constants can be initialized. */ public CompactCodeAttributeComposer( ProgramClass targetClass, boolean allowExternalBranchTargets, boolean allowExternalExceptionOffsets, boolean shrinkInstructions, ClassPool programClassPool, ClassPool libraryClassPool) { this( new ConstantPoolEditor(targetClass, programClassPool, libraryClassPool), allowExternalBranchTargets, allowExternalExceptionOffsets, shrinkInstructions); } /** * Creates a new CompactCodeAttributeComposer. * * @param constantPoolEditor an editor for the constants in the class. * @param allowExternalBranchTargets specifies whether branch targets can lie outside the code * fragment of the branch instructions. * @param allowExternalExceptionOffsets specifies whether exception offsets can lie outside the * code fragment in which exceptions are defined. * @param shrinkInstructions specifies whether instructions should automatically be shrunk before * being written. */ public CompactCodeAttributeComposer( ConstantPoolEditor constantPoolEditor, boolean allowExternalBranchTargets, boolean allowExternalExceptionOffsets, boolean shrinkInstructions) { this( constantPoolEditor, new CodeAttributeComposer( allowExternalBranchTargets, allowExternalExceptionOffsets, shrinkInstructions, true)); } /** * Creates a new CompactCodeAttributeComposer. * * @param constantPoolEditor an editor for the constants in the class. * @param codeAttributeComposer an composer for the instructions in the method. */ public CompactCodeAttributeComposer( ConstantPoolEditor constantPoolEditor, CodeAttributeComposer codeAttributeComposer) { this.constantPoolEditor = constantPoolEditor; this.codeAttributeComposer = codeAttributeComposer; } /** Returns the target class for which code is generated. */ public ProgramClass getTargetClass() { return constantPoolEditor.getTargetClass(); } /** * Returns a ConstantPoolEditor instance for the created or edited class instance. Reusing this * instance is more efficient for classes that are created from scratch. */ public ConstantPoolEditor getConstantPoolEditor() { return constantPoolEditor; } /** Returns the current length (in bytes) of the code attribute being composed. */ public int getCodeLength() { return codeAttributeComposer.getCodeLength(); } /** * Adds the required instructions to the provided CodeAttributeComposer to convert the current * value on the stack to the given targetType. */ public CompactCodeAttributeComposer convertToTargetType(String sourceType, String targetType) { if (ClassUtil.isInternalPrimitiveType(sourceType) && !ClassUtil.isInternalPrimitiveType(targetType)) { this.boxPrimitiveType(sourceType.charAt(0)); } else if (!ClassUtil.isInternalPrimitiveType(sourceType) && ClassUtil.isInternalPrimitiveType(targetType)) { this.unboxPrimitiveType(sourceType, targetType); } else if (ClassUtil.isInternalClassType(sourceType) && (ClassUtil.isInternalClassType(targetType) || ClassUtil.isInternalArrayType(targetType)) && !sourceType.equals(targetType) && // No need to cast to java/lang/Object. !TYPE_JAVA_LANG_OBJECT.equals(targetType)) { // Cast to target type. this.checkcast(ClassUtil.internalClassTypeFromType(targetType)); } else if (ClassUtil.isInternalPrimitiveType(sourceType) && ClassUtil.isInternalPrimitiveType(targetType) && !sourceType.equals(targetType)) { char source = sourceType.charAt(0); char target = targetType.charAt(0); this.convertPrimitiveType(source, target); } return this; } /** * Box the primitive value present on the stack. * *

Operand stack: ..., primitive -> ..., boxed_primitive * * @param sourceType type of the primitive on the stack. */ public CompactCodeAttributeComposer boxPrimitiveType(char sourceType) { // Perform auto-boxing. switch (sourceType) { case TypeConstants.INT: this.invokestatic(NAME_JAVA_LANG_INTEGER, METHOD_NAME_VALUEOF, METHOD_TYPE_VALUE_OF_INT); break; case TypeConstants.BYTE: this.invokestatic(NAME_JAVA_LANG_BYTE, METHOD_NAME_VALUEOF, METHOD_TYPE_VALUE_OF_BYTE); break; case TypeConstants.CHAR: this.invokestatic(NAME_JAVA_LANG_CHARACTER, METHOD_NAME_VALUEOF, METHOD_TYPE_VALUE_OF_CHAR); break; case TypeConstants.SHORT: this.invokestatic(NAME_JAVA_LANG_SHORT, METHOD_NAME_VALUEOF, METHOD_TYPE_VALUE_OF_SHORT); break; case TypeConstants.BOOLEAN: this.invokestatic( NAME_JAVA_LANG_BOOLEAN, METHOD_NAME_VALUEOF, METHOD_TYPE_VALUE_OF_BOOLEAN); break; case TypeConstants.LONG: this.invokestatic(NAME_JAVA_LANG_LONG, METHOD_NAME_VALUEOF, METHOD_TYPE_VALUE_OF_LONG); break; case TypeConstants.FLOAT: this.invokestatic(NAME_JAVA_LANG_FLOAT, METHOD_NAME_VALUEOF, METHOD_TYPE_VALUE_OF_FLOAT); break; case TypeConstants.DOUBLE: this.invokestatic(NAME_JAVA_LANG_DOUBLE, METHOD_NAME_VALUEOF, METHOD_TYPE_VALUE_OF_DOUBLE); break; } return this; } /** * Add instructions to convert the primitive on the stack to a different primitive type. * * @param source The source type. * @param target The target type. */ public CompactCodeAttributeComposer convertPrimitiveType(char source, char target) { // If we start from a short, byte or char, we can treat it as an int without instructions if (source == TypeConstants.SHORT || source == TypeConstants.BYTE || source == TypeConstants.CHAR) { source = TypeConstants.INT; } switch (source) { case TypeConstants.INT: switch (target) { case TypeConstants.DOUBLE: this.i2d(); break; case TypeConstants.BYTE: this.i2b(); break; case TypeConstants.CHAR: this.i2c(); break; case TypeConstants.FLOAT: this.i2f(); break; case TypeConstants.LONG: this.i2l(); break; case TypeConstants.SHORT: this.i2s(); break; } break; case TypeConstants.FLOAT: switch (target) { case TypeConstants.DOUBLE: this.f2d(); break; case TypeConstants.BYTE: this.f2i(); this.i2b(); break; case TypeConstants.CHAR: this.f2i(); this.i2c(); break; case TypeConstants.INT: this.f2i(); break; case TypeConstants.LONG: this.f2l(); break; case TypeConstants.SHORT: this.f2i(); this.i2s(); break; } break; case TypeConstants.DOUBLE: switch (target) { case TypeConstants.INT: this.d2i(); break; case TypeConstants.BYTE: this.d2i(); this.i2b(); break; case TypeConstants.CHAR: this.d2i(); this.i2c(); break; case TypeConstants.FLOAT: this.d2f(); break; case TypeConstants.LONG: this.d2l(); break; case TypeConstants.SHORT: this.d2i(); this.i2s(); break; } break; case TypeConstants.LONG: switch (target) { case TypeConstants.DOUBLE: this.l2d(); break; case TypeConstants.BYTE: this.l2i(); this.i2b(); break; case TypeConstants.CHAR: this.l2i(); this.i2c(); break; case TypeConstants.FLOAT: this.l2f(); break; case TypeConstants.INT: this.l2i(); break; case TypeConstants.SHORT: this.l2i(); this.i2s(); break; } break; } return this; } /** * Unbox the object on the stack to a primitive value. * *

Operand stack: ..., boxed_primitive -> ..., primitive * * @param sourceType type of the primitive that should be unboxed. * @param targetType resulting type. */ public CompactCodeAttributeComposer unboxPrimitiveType(String sourceType, String targetType) { boolean castRequired = sourceType.equals(TYPE_JAVA_LANG_OBJECT); // Perform auto-unboxing. switch (targetType.charAt(0)) { case TypeConstants.INT: if (castRequired) { this.checkcast(NAME_JAVA_LANG_NUMBER); } this.invokevirtual(NAME_JAVA_LANG_NUMBER, METHOD_NAME_INT_VALUE, METHOD_TYPE_INT_VALUE); break; case TypeConstants.BYTE: if (castRequired) { this.checkcast(NAME_JAVA_LANG_BYTE); } this.invokevirtual(NAME_JAVA_LANG_BYTE, METHOD_NAME_BYTE_VALUE, METHOD_TYPE_BYTE_VALUE); break; case TypeConstants.CHAR: if (castRequired) { this.checkcast(NAME_JAVA_LANG_CHARACTER); } this.invokevirtual( NAME_JAVA_LANG_CHARACTER, METHOD_NAME_CHAR_VALUE, METHOD_TYPE_CHAR_VALUE); break; case TypeConstants.SHORT: if (castRequired) { this.checkcast(NAME_JAVA_LANG_SHORT); } this.invokevirtual(NAME_JAVA_LANG_SHORT, METHOD_NAME_SHORT_VALUE, METHOD_TYPE_SHORT_VALUE); break; case TypeConstants.BOOLEAN: if (castRequired) { this.checkcast(NAME_JAVA_LANG_BOOLEAN); } this.invokevirtual( NAME_JAVA_LANG_BOOLEAN, METHOD_NAME_BOOLEAN_VALUE, METHOD_TYPE_BOOLEAN_VALUE); break; case TypeConstants.LONG: if (castRequired) { this.checkcast(NAME_JAVA_LANG_NUMBER); } this.invokevirtual(NAME_JAVA_LANG_NUMBER, METHOD_NAME_LONG_VALUE, METHOD_TYPE_LONG_VALUE); break; case TypeConstants.FLOAT: if (castRequired) { this.checkcast(NAME_JAVA_LANG_NUMBER); } this.invokevirtual(NAME_JAVA_LANG_NUMBER, METHOD_NAME_FLOAT_VALUE, METHOD_TYPE_FLOAT_VALUE); break; case TypeConstants.DOUBLE: if (castRequired) { this.checkcast(NAME_JAVA_LANG_NUMBER); } this.invokevirtual( NAME_JAVA_LANG_NUMBER, METHOD_NAME_DOUBLE_VALUE, METHOD_TYPE_DOUBLE_VALUE); break; } return this; } /** Starts a new code definition. */ public CompactCodeAttributeComposer reset() { codeAttributeComposer.reset(); labelCount = 0; return this; } /** * Starts a new code fragment. Branch instructions that are added are assumed to be relative * within such code fragments. * * @param maximumCodeFragmentLength the maximum length of the code that will be added as part of * this fragment (more precisely, the maximum old instruction offset or label that is * specified, plus one). * @return this instance of CompactCodeAttributeComposer. */ public CompactCodeAttributeComposer beginCodeFragment(int maximumCodeFragmentLength) { codeAttributeComposer.beginCodeFragment(maximumCodeFragmentLength); return this; } /** Creates a new label that can be specified and used in the code. */ public Label createLabel() { return new Label(labelCount++); } /** * Appends the given label at the current offset, so branch instructions and switch instructions * can jump to it. * * @param label the branch label. * @return this instance of CompactCodeAttributeComposer. */ public CompactCodeAttributeComposer label(Label label) { codeAttributeComposer.appendLabel(label.offset); return this; } /** * Appends the given instruction without defined offsets. * * @param instructions the instructions to be appended. * @return this instance of CompactCodeAttributeComposer. */ public CompactCodeAttributeComposer appendInstructions(Instruction[] instructions) { codeAttributeComposer.appendInstructions(instructions); return this; } /** * Appends the given instruction. * * @param instruction the instruction to be appended. * @return this instance of CompactCodeAttributeComposer. */ public CompactCodeAttributeComposer appendInstruction(Instruction instruction) { codeAttributeComposer.appendInstruction(instruction); return this; } /** * Starts a catch-all handler at the current offset. * * @param startLabel the start label of the try block. * @param endLabel the end label of the try block. * @return this instance of CompactCodeAttributeComposer. */ public CompactCodeAttributeComposer catchAll(Label startLabel, Label endLabel) { return catch_(startLabel, endLabel, null, null); } /** * Adds a catch-all handler. * * @param startLabel the start label of the try block. * @param endLabel the end label of the try block. * @param handlerLabel the label of the exception handler. * @return this instance of CompactCodeAttributeComposer. */ public CompactCodeAttributeComposer catchAll( Label startLabel, Label endLabel, Label handlerLabel) { return catch_(startLabel, endLabel, handlerLabel, null, null); } /** * Starts a catch handler at the current offset. * * @param startLabel the start label of the try block. * @param endLabel the end label of the try block. * @param catchType the exception type. * @param referencedClass the exception class, if known. * @return this instance of CompactCodeAttributeComposer. */ public CompactCodeAttributeComposer catch_( Label startLabel, Label endLabel, String catchType, Clazz referencedClass) { // Create and append a label for the current offset. Label handlerLabel = createLabel(); codeAttributeComposer.appendLabel(handlerLabel.offset); return catch_(startLabel, endLabel, handlerLabel, catchType, referencedClass); } /** * Adds a catch handler. * * @param startLabel the start label of the try block. * @param endLabel the end label of the try block. * @param handlerLabel the label of the exception handler. * @param catchType the exception type. * @param referencedClass the exception class, if known. * @return this instance of CompactCodeAttributeComposer. */ public CompactCodeAttributeComposer catch_( Label startLabel, Label endLabel, Label handlerLabel, String catchType, Clazz referencedClass) { // Create and append the exception. int u2catchType = (catchType == null) ? 0 : constantPoolEditor.addClassConstant(catchType, referencedClass); codeAttributeComposer.appendException( new ExceptionInfo(startLabel.offset, endLabel.offset, handlerLabel.offset, u2catchType)); return this; } /** * Adds a source line number for the current position. * * @param lineNumber the line number from the source code. * @return this instance of CompactCodeAttributeComposer. */ public CompactCodeAttributeComposer line(int lineNumber) { // Create and append a label for the current offset. Label currentLabel = createLabel(); codeAttributeComposer.appendLabel(currentLabel.offset); // Create and append the line number. codeAttributeComposer.appendLineNumber(new LineNumberInfo(currentLabel.offset, lineNumber)); return this; } /** * Wraps up the current code fragment, continuing with the previous one on the stack. * * @return this instance of CompactCodeAttributeComposer. */ public CompactCodeAttributeComposer endCodeFragment() { codeAttributeComposer.endCodeFragment(); return this; } // Methods corresponding to the bytecode opcodes. public CompactCodeAttributeComposer nop() { return appendInstruction(new SimpleInstruction(Instruction.OP_NOP)); } public CompactCodeAttributeComposer aconst_null() { return appendInstruction(new SimpleInstruction(Instruction.OP_ACONST_NULL)); } public CompactCodeAttributeComposer iconst(int constant) { return appendInstruction(new SimpleInstruction(Instruction.OP_ICONST_0, constant)); } public CompactCodeAttributeComposer iconst_m1() { return appendInstruction(new SimpleInstruction(Instruction.OP_ICONST_M1)); } public CompactCodeAttributeComposer iconst_0() { return appendInstruction(new SimpleInstruction(Instruction.OP_ICONST_0)); } public CompactCodeAttributeComposer iconst_1() { return appendInstruction(new SimpleInstruction(Instruction.OP_ICONST_1)); } public CompactCodeAttributeComposer iconst_2() { return appendInstruction(new SimpleInstruction(Instruction.OP_ICONST_2)); } public CompactCodeAttributeComposer iconst_3() { return appendInstruction(new SimpleInstruction(Instruction.OP_ICONST_3)); } public CompactCodeAttributeComposer iconst_4() { return appendInstruction(new SimpleInstruction(Instruction.OP_ICONST_4)); } public CompactCodeAttributeComposer iconst_5() { return appendInstruction(new SimpleInstruction(Instruction.OP_ICONST_5)); } public CompactCodeAttributeComposer lconst(int constant) { return appendInstruction(new SimpleInstruction(Instruction.OP_LCONST_0, constant)); } public CompactCodeAttributeComposer lconst_0() { return appendInstruction(new SimpleInstruction(Instruction.OP_LCONST_0)); } public CompactCodeAttributeComposer lconst_1() { return appendInstruction(new SimpleInstruction(Instruction.OP_LCONST_1)); } public CompactCodeAttributeComposer fconst(int constant) { return appendInstruction(new SimpleInstruction(Instruction.OP_FCONST_0, constant)); } public CompactCodeAttributeComposer fconst_0() { return appendInstruction(new SimpleInstruction(Instruction.OP_FCONST_0)); } public CompactCodeAttributeComposer fconst_1() { return appendInstruction(new SimpleInstruction(Instruction.OP_FCONST_1)); } public CompactCodeAttributeComposer fconst_2() { return appendInstruction(new SimpleInstruction(Instruction.OP_FCONST_2)); } public CompactCodeAttributeComposer dconst(int constant) { return appendInstruction(new SimpleInstruction(Instruction.OP_DCONST_0, constant)); } public CompactCodeAttributeComposer dconst_0() { return appendInstruction(new SimpleInstruction(Instruction.OP_DCONST_0)); } public CompactCodeAttributeComposer dconst_1() { return appendInstruction(new SimpleInstruction(Instruction.OP_DCONST_1)); } public CompactCodeAttributeComposer bipush(int constant) { return appendInstruction(new SimpleInstruction(Instruction.OP_BIPUSH, constant)); } public CompactCodeAttributeComposer sipush(int constant) { return appendInstruction(new SimpleInstruction(Instruction.OP_SIPUSH, constant)); } /** Appends an ldc instruction that loads an integer constant with the given value. */ public CompactCodeAttributeComposer ldc(int value) { return ldc_(constantPoolEditor.addIntegerConstant(value)); } /** Appends an ldc instruction that loads a float constant with the given value. */ public CompactCodeAttributeComposer ldc(float value) { return ldc_(constantPoolEditor.addFloatConstant(value)); } /** Appends an ldc instruction that loads a string constant with the given value. */ public CompactCodeAttributeComposer ldc(String string) { return ldc(string, null, null); } /** * Appends an ldc instruction that loads an (internal) primitive array constant with the given * value. */ public CompactCodeAttributeComposer ldc(Object primitiveArray) { return ldc_(constantPoolEditor.addPrimitiveArrayConstant(primitiveArray)); } /** Appends an ldc instruction that loads a string constant with the given class member name. */ public CompactCodeAttributeComposer ldc(Clazz clazz, Member member) { return ldc(member.getName(clazz), clazz, member); } /** * Appends an ldc instruction that loads a string constant with the given value, that references * the given class member. */ public CompactCodeAttributeComposer ldc( String string, Clazz referencedClass, Member referencedMember) { return ldc_(constantPoolEditor.addStringConstant(string, referencedClass, referencedMember)); } /** Appends an ldc instruction that loads a string constant with the given resource file name. */ public CompactCodeAttributeComposer ldc(ResourceFile resourceFile) { return ldc(resourceFile.getFileName(), resourceFile); } /** * Appends an ldc instruction that loads a string constant with the given value, that references * the given resource file. */ public CompactCodeAttributeComposer ldc(String string, ResourceFile referencedResourceFile) { return ldc_(constantPoolEditor.addStringConstant(string, referencedResourceFile)); } /** Appends an ldc instruction that loads a class constant for the given class. */ public CompactCodeAttributeComposer ldc(Clazz clazz) { return ldc(clazz.getName(), clazz); } /** * Appends an ldc instruction that loads a class constant for the given type name, that references * the given class. */ public CompactCodeAttributeComposer ldc(String typeName, Clazz referencedClass) { return ldc_(constantPoolEditor.addClassConstant(typeName, referencedClass)); } /** Appends an ldc instruction that loads the constant at the given index. */ public CompactCodeAttributeComposer ldc_(int constantIndex) { return appendInstruction(new ConstantInstruction(Instruction.OP_LDC, constantIndex)); } /** Appends an ldc_w instruction that loads an integer constant with the given value. */ public CompactCodeAttributeComposer ldc_w(int value) { return ldc_(constantPoolEditor.addIntegerConstant(value)); } /** Appends an ldc_w instruction that loads a float constant with the given value. */ public CompactCodeAttributeComposer ldc_w(float value) { return ldc_(constantPoolEditor.addFloatConstant(value)); } /** Appends an ldc_w instruction that loads a string constant with the given value. */ public CompactCodeAttributeComposer ldc_w(String string) { return ldc_w(string, null, null); } /** * Appends an ldc_w instruction that loads an (internal) primitive array constant with the given * value. */ public CompactCodeAttributeComposer ldc_w(Object primitiveArray) { return ldc_(constantPoolEditor.addPrimitiveArrayConstant(primitiveArray)); } /** Appends an ldc_w instruction that loads a string constant with the given class member name. */ public CompactCodeAttributeComposer ldc_w(Clazz clazz, Member member) { return ldc_w(member.getName(clazz), clazz, member); } /** * Appends an ldc_w instruction that loads a string constant with the given value, that references * the given class member. */ public CompactCodeAttributeComposer ldc_w( String string, Clazz referencedClass, Member referencedMember) { return ldc_(constantPoolEditor.addStringConstant(string, referencedClass, referencedMember)); } /** * Appends an ldc_w instruction that loads a string constant with the given resource file name. */ public CompactCodeAttributeComposer ldc_w(ResourceFile resourceFile) { return ldc_w(resourceFile.getFileName(), resourceFile); } /** * Appends an ldc_w instruction that loads a string constant with the given value, that references * the given resource file. */ public CompactCodeAttributeComposer ldc_w(String string, ResourceFile referencedResourceFile) { return ldc_(constantPoolEditor.addStringConstant(string, referencedResourceFile)); } /** Appends an ldc_w instruction that loads a class constant for the given class. */ public CompactCodeAttributeComposer ldc_w(Clazz clazz) { return ldc_w(clazz.getName(), clazz); } /** * Appends an ldc_w instruction that loads a class constant for the given type name, that * references the given class. */ public CompactCodeAttributeComposer ldc_w(String typeName, Clazz referencedClass) { return ldc_(constantPoolEditor.addClassConstant(typeName, referencedClass)); } /** Appends an ldc_w instruction that loads the constant at the given index. */ public CompactCodeAttributeComposer ldc_w_(int constantIndex) { return appendInstruction(new ConstantInstruction(Instruction.OP_LDC_W, constantIndex)); } /** Appends an ldc2_w instruction that loads a long constant with the given value. */ public CompactCodeAttributeComposer ldc2_w(long value) { return ldc2_w(constantPoolEditor.addLongConstant(value)); } /** Appends an ldc2_w instruction that loads a double constant with the given value. */ public CompactCodeAttributeComposer ldc2_w(double value) { return ldc2_w(constantPoolEditor.addDoubleConstant(value)); } /** Appends an ldc2_w instruction that loads the Category 2 constant at the given index. */ public CompactCodeAttributeComposer ldc2_w(int constantIndex) { return appendInstruction(new ConstantInstruction(Instruction.OP_LDC2_W, constantIndex)); } public CompactCodeAttributeComposer iload(int variableIndex) { return appendInstruction(new VariableInstruction(Instruction.OP_ILOAD, variableIndex)); } public CompactCodeAttributeComposer lload(int variableIndex) { return appendInstruction(new VariableInstruction(Instruction.OP_LLOAD, variableIndex)); } public CompactCodeAttributeComposer fload(int variableIndex) { return appendInstruction(new VariableInstruction(Instruction.OP_FLOAD, variableIndex)); } public CompactCodeAttributeComposer dload(int variableIndex) { return appendInstruction(new VariableInstruction(Instruction.OP_DLOAD, variableIndex)); } public CompactCodeAttributeComposer aload(int variableIndex) { return appendInstruction(new VariableInstruction(Instruction.OP_ALOAD, variableIndex)); } public CompactCodeAttributeComposer iload_0() { return appendInstruction(new VariableInstruction(Instruction.OP_ILOAD_0)); } public CompactCodeAttributeComposer iload_1() { return appendInstruction(new VariableInstruction(Instruction.OP_ILOAD_1)); } public CompactCodeAttributeComposer iload_2() { return appendInstruction(new VariableInstruction(Instruction.OP_ILOAD_2)); } public CompactCodeAttributeComposer iload_3() { return appendInstruction(new VariableInstruction(Instruction.OP_ILOAD_3)); } public CompactCodeAttributeComposer lload_0() { return appendInstruction(new VariableInstruction(Instruction.OP_LLOAD_0)); } public CompactCodeAttributeComposer lload_1() { return appendInstruction(new VariableInstruction(Instruction.OP_LLOAD_1)); } public CompactCodeAttributeComposer lload_2() { return appendInstruction(new VariableInstruction(Instruction.OP_LLOAD_2)); } public CompactCodeAttributeComposer lload_3() { return appendInstruction(new VariableInstruction(Instruction.OP_LLOAD_3)); } public CompactCodeAttributeComposer fload_0() { return appendInstruction(new VariableInstruction(Instruction.OP_FLOAD_0)); } public CompactCodeAttributeComposer fload_1() { return appendInstruction(new VariableInstruction(Instruction.OP_FLOAD_1)); } public CompactCodeAttributeComposer fload_2() { return appendInstruction(new VariableInstruction(Instruction.OP_FLOAD_2)); } public CompactCodeAttributeComposer fload_3() { return appendInstruction(new VariableInstruction(Instruction.OP_FLOAD_3)); } public CompactCodeAttributeComposer dload_0() { return appendInstruction(new VariableInstruction(Instruction.OP_DLOAD_0)); } public CompactCodeAttributeComposer dload_1() { return appendInstruction(new VariableInstruction(Instruction.OP_DLOAD_1)); } public CompactCodeAttributeComposer dload_2() { return appendInstruction(new VariableInstruction(Instruction.OP_DLOAD_2)); } public CompactCodeAttributeComposer dload_3() { return appendInstruction(new VariableInstruction(Instruction.OP_DLOAD_3)); } public CompactCodeAttributeComposer aload_0() { return appendInstruction(new VariableInstruction(Instruction.OP_ALOAD_0)); } public CompactCodeAttributeComposer aload_1() { return appendInstruction(new VariableInstruction(Instruction.OP_ALOAD_1)); } public CompactCodeAttributeComposer aload_2() { return appendInstruction(new VariableInstruction(Instruction.OP_ALOAD_2)); } public CompactCodeAttributeComposer aload_3() { return appendInstruction(new VariableInstruction(Instruction.OP_ALOAD_3)); } public CompactCodeAttributeComposer iaload() { return appendInstruction(new SimpleInstruction(Instruction.OP_IALOAD)); } public CompactCodeAttributeComposer laload() { return appendInstruction(new SimpleInstruction(Instruction.OP_LALOAD)); } public CompactCodeAttributeComposer faload() { return appendInstruction(new SimpleInstruction(Instruction.OP_FALOAD)); } public CompactCodeAttributeComposer daload() { return appendInstruction(new SimpleInstruction(Instruction.OP_DALOAD)); } public CompactCodeAttributeComposer aaload() { return appendInstruction(new SimpleInstruction(Instruction.OP_AALOAD)); } public CompactCodeAttributeComposer baload() { return appendInstruction(new SimpleInstruction(Instruction.OP_BALOAD)); } public CompactCodeAttributeComposer caload() { return appendInstruction(new SimpleInstruction(Instruction.OP_CALOAD)); } public CompactCodeAttributeComposer saload() { return appendInstruction(new SimpleInstruction(Instruction.OP_SALOAD)); } public CompactCodeAttributeComposer istore(int variableIndex) { return appendInstruction(new VariableInstruction(Instruction.OP_ISTORE, variableIndex)); } public CompactCodeAttributeComposer lstore(int variableIndex) { return appendInstruction(new VariableInstruction(Instruction.OP_LSTORE, variableIndex)); } public CompactCodeAttributeComposer fstore(int variableIndex) { return appendInstruction(new VariableInstruction(Instruction.OP_FSTORE, variableIndex)); } public CompactCodeAttributeComposer dstore(int variableIndex) { return appendInstruction(new VariableInstruction(Instruction.OP_DSTORE, variableIndex)); } public CompactCodeAttributeComposer astore(int variableIndex) { return appendInstruction(new VariableInstruction(Instruction.OP_ASTORE, variableIndex)); } public CompactCodeAttributeComposer istore_0() { return appendInstruction(new VariableInstruction(Instruction.OP_ISTORE_0)); } public CompactCodeAttributeComposer istore_1() { return appendInstruction(new VariableInstruction(Instruction.OP_ISTORE_1)); } public CompactCodeAttributeComposer istore_2() { return appendInstruction(new VariableInstruction(Instruction.OP_ISTORE_2)); } public CompactCodeAttributeComposer istore_3() { return appendInstruction(new VariableInstruction(Instruction.OP_ISTORE_3)); } public CompactCodeAttributeComposer lstore_0() { return appendInstruction(new VariableInstruction(Instruction.OP_LSTORE_0)); } public CompactCodeAttributeComposer lstore_1() { return appendInstruction(new VariableInstruction(Instruction.OP_LSTORE_1)); } public CompactCodeAttributeComposer lstore_2() { return appendInstruction(new VariableInstruction(Instruction.OP_LSTORE_2)); } public CompactCodeAttributeComposer lstore_3() { return appendInstruction(new VariableInstruction(Instruction.OP_LSTORE_3)); } public CompactCodeAttributeComposer fstore_0() { return appendInstruction(new VariableInstruction(Instruction.OP_FSTORE_0)); } public CompactCodeAttributeComposer fstore_1() { return appendInstruction(new VariableInstruction(Instruction.OP_FSTORE_1)); } public CompactCodeAttributeComposer fstore_2() { return appendInstruction(new VariableInstruction(Instruction.OP_FSTORE_2)); } public CompactCodeAttributeComposer fstore_3() { return appendInstruction(new VariableInstruction(Instruction.OP_FSTORE_3)); } public CompactCodeAttributeComposer dstore_0() { return appendInstruction(new VariableInstruction(Instruction.OP_DSTORE_0)); } public CompactCodeAttributeComposer dstore_1() { return appendInstruction(new VariableInstruction(Instruction.OP_DSTORE_1)); } public CompactCodeAttributeComposer dstore_2() { return appendInstruction(new VariableInstruction(Instruction.OP_DSTORE_2)); } public CompactCodeAttributeComposer dstore_3() { return appendInstruction(new VariableInstruction(Instruction.OP_DSTORE_3)); } public CompactCodeAttributeComposer astore_0() { return appendInstruction(new VariableInstruction(Instruction.OP_ASTORE_0)); } public CompactCodeAttributeComposer astore_1() { return appendInstruction(new VariableInstruction(Instruction.OP_ASTORE_1)); } public CompactCodeAttributeComposer astore_2() { return appendInstruction(new VariableInstruction(Instruction.OP_ASTORE_2)); } public CompactCodeAttributeComposer astore_3() { return appendInstruction(new VariableInstruction(Instruction.OP_ASTORE_3)); } public CompactCodeAttributeComposer iastore() { return appendInstruction(new SimpleInstruction(Instruction.OP_IASTORE)); } public CompactCodeAttributeComposer lastore() { return appendInstruction(new SimpleInstruction(Instruction.OP_LASTORE)); } public CompactCodeAttributeComposer fastore() { return appendInstruction(new SimpleInstruction(Instruction.OP_FASTORE)); } public CompactCodeAttributeComposer dastore() { return appendInstruction(new SimpleInstruction(Instruction.OP_DASTORE)); } public CompactCodeAttributeComposer aastore() { return appendInstruction(new SimpleInstruction(Instruction.OP_AASTORE)); } public CompactCodeAttributeComposer bastore() { return appendInstruction(new SimpleInstruction(Instruction.OP_BASTORE)); } public CompactCodeAttributeComposer castore() { return appendInstruction(new SimpleInstruction(Instruction.OP_CASTORE)); } public CompactCodeAttributeComposer sastore() { return appendInstruction(new SimpleInstruction(Instruction.OP_SASTORE)); } public CompactCodeAttributeComposer pop() { return appendInstruction(new SimpleInstruction(Instruction.OP_POP)); } public CompactCodeAttributeComposer pop2() { return appendInstruction(new SimpleInstruction(Instruction.OP_POP2)); } public CompactCodeAttributeComposer dup() { return appendInstruction(new SimpleInstruction(Instruction.OP_DUP)); } public CompactCodeAttributeComposer dup_x1() { return appendInstruction(new SimpleInstruction(Instruction.OP_DUP_X1)); } public CompactCodeAttributeComposer dup_x2() { return appendInstruction(new SimpleInstruction(Instruction.OP_DUP_X2)); } public CompactCodeAttributeComposer dup2() { return appendInstruction(new SimpleInstruction(Instruction.OP_DUP2)); } public CompactCodeAttributeComposer dup2_x1() { return appendInstruction(new SimpleInstruction(Instruction.OP_DUP2_X1)); } public CompactCodeAttributeComposer dup2_x2() { return appendInstruction(new SimpleInstruction(Instruction.OP_DUP2_X2)); } public CompactCodeAttributeComposer swap() { return appendInstruction(new SimpleInstruction(Instruction.OP_SWAP)); } public CompactCodeAttributeComposer iadd() { return appendInstruction(new SimpleInstruction(Instruction.OP_IADD)); } public CompactCodeAttributeComposer ladd() { return appendInstruction(new SimpleInstruction(Instruction.OP_LADD)); } public CompactCodeAttributeComposer fadd() { return appendInstruction(new SimpleInstruction(Instruction.OP_FADD)); } public CompactCodeAttributeComposer dadd() { return appendInstruction(new SimpleInstruction(Instruction.OP_DADD)); } public CompactCodeAttributeComposer isub() { return appendInstruction(new SimpleInstruction(Instruction.OP_ISUB)); } public CompactCodeAttributeComposer lsub() { return appendInstruction(new SimpleInstruction(Instruction.OP_LSUB)); } public CompactCodeAttributeComposer fsub() { return appendInstruction(new SimpleInstruction(Instruction.OP_FSUB)); } public CompactCodeAttributeComposer dsub() { return appendInstruction(new SimpleInstruction(Instruction.OP_DSUB)); } public CompactCodeAttributeComposer imul() { return appendInstruction(new SimpleInstruction(Instruction.OP_IMUL)); } public CompactCodeAttributeComposer lmul() { return appendInstruction(new SimpleInstruction(Instruction.OP_LMUL)); } public CompactCodeAttributeComposer fmul() { return appendInstruction(new SimpleInstruction(Instruction.OP_FMUL)); } public CompactCodeAttributeComposer dmul() { return appendInstruction(new SimpleInstruction(Instruction.OP_DMUL)); } public CompactCodeAttributeComposer idiv() { return appendInstruction(new SimpleInstruction(Instruction.OP_IDIV)); } public CompactCodeAttributeComposer ldiv() { return appendInstruction(new SimpleInstruction(Instruction.OP_LDIV)); } public CompactCodeAttributeComposer fdiv() { return appendInstruction(new SimpleInstruction(Instruction.OP_FDIV)); } public CompactCodeAttributeComposer ddiv() { return appendInstruction(new SimpleInstruction(Instruction.OP_DDIV)); } public CompactCodeAttributeComposer irem() { return appendInstruction(new SimpleInstruction(Instruction.OP_IREM)); } public CompactCodeAttributeComposer lrem() { return appendInstruction(new SimpleInstruction(Instruction.OP_LREM)); } public CompactCodeAttributeComposer frem() { return appendInstruction(new SimpleInstruction(Instruction.OP_FREM)); } public CompactCodeAttributeComposer drem() { return appendInstruction(new SimpleInstruction(Instruction.OP_DREM)); } public CompactCodeAttributeComposer ineg() { return appendInstruction(new SimpleInstruction(Instruction.OP_INEG)); } public CompactCodeAttributeComposer lneg() { return appendInstruction(new SimpleInstruction(Instruction.OP_LNEG)); } public CompactCodeAttributeComposer fneg() { return appendInstruction(new SimpleInstruction(Instruction.OP_FNEG)); } public CompactCodeAttributeComposer dneg() { return appendInstruction(new SimpleInstruction(Instruction.OP_DNEG)); } public CompactCodeAttributeComposer ishl() { return appendInstruction(new SimpleInstruction(Instruction.OP_ISHL)); } public CompactCodeAttributeComposer lshl() { return appendInstruction(new SimpleInstruction(Instruction.OP_LSHL)); } public CompactCodeAttributeComposer ishr() { return appendInstruction(new SimpleInstruction(Instruction.OP_ISHR)); } public CompactCodeAttributeComposer lshr() { return appendInstruction(new SimpleInstruction(Instruction.OP_LSHR)); } public CompactCodeAttributeComposer iushr() { return appendInstruction(new SimpleInstruction(Instruction.OP_IUSHR)); } public CompactCodeAttributeComposer lushr() { return appendInstruction(new SimpleInstruction(Instruction.OP_LUSHR)); } public CompactCodeAttributeComposer iand() { return appendInstruction(new SimpleInstruction(Instruction.OP_IAND)); } public CompactCodeAttributeComposer land() { return appendInstruction(new SimpleInstruction(Instruction.OP_LAND)); } public CompactCodeAttributeComposer ior() { return appendInstruction(new SimpleInstruction(Instruction.OP_IOR)); } public CompactCodeAttributeComposer lor() { return appendInstruction(new SimpleInstruction(Instruction.OP_LOR)); } public CompactCodeAttributeComposer ixor() { return appendInstruction(new SimpleInstruction(Instruction.OP_IXOR)); } public CompactCodeAttributeComposer lxor() { return appendInstruction(new SimpleInstruction(Instruction.OP_LXOR)); } public CompactCodeAttributeComposer iinc(int variableIndex, int constant) { return appendInstruction(new VariableInstruction(Instruction.OP_IINC, variableIndex, constant)); } public CompactCodeAttributeComposer i2l() { return appendInstruction(new SimpleInstruction(Instruction.OP_I2L)); } public CompactCodeAttributeComposer i2f() { return appendInstruction(new SimpleInstruction(Instruction.OP_I2F)); } public CompactCodeAttributeComposer i2d() { return appendInstruction(new SimpleInstruction(Instruction.OP_I2D)); } public CompactCodeAttributeComposer l2i() { return appendInstruction(new SimpleInstruction(Instruction.OP_L2I)); } public CompactCodeAttributeComposer l2f() { return appendInstruction(new SimpleInstruction(Instruction.OP_L2F)); } public CompactCodeAttributeComposer l2d() { return appendInstruction(new SimpleInstruction(Instruction.OP_L2D)); } public CompactCodeAttributeComposer f2i() { return appendInstruction(new SimpleInstruction(Instruction.OP_F2I)); } public CompactCodeAttributeComposer f2l() { return appendInstruction(new SimpleInstruction(Instruction.OP_F2L)); } public CompactCodeAttributeComposer f2d() { return appendInstruction(new SimpleInstruction(Instruction.OP_F2D)); } public CompactCodeAttributeComposer d2i() { return appendInstruction(new SimpleInstruction(Instruction.OP_D2I)); } public CompactCodeAttributeComposer d2l() { return appendInstruction(new SimpleInstruction(Instruction.OP_D2L)); } public CompactCodeAttributeComposer d2f() { return appendInstruction(new SimpleInstruction(Instruction.OP_D2F)); } public CompactCodeAttributeComposer i2b() { return appendInstruction(new SimpleInstruction(Instruction.OP_I2B)); } public CompactCodeAttributeComposer i2c() { return appendInstruction(new SimpleInstruction(Instruction.OP_I2C)); } public CompactCodeAttributeComposer i2s() { return appendInstruction(new SimpleInstruction(Instruction.OP_I2S)); } public CompactCodeAttributeComposer lcmp() { return appendInstruction(new SimpleInstruction(Instruction.OP_LCMP)); } public CompactCodeAttributeComposer fcmpl() { return appendInstruction(new SimpleInstruction(Instruction.OP_FCMPL)); } public CompactCodeAttributeComposer fcmpg() { return appendInstruction(new SimpleInstruction(Instruction.OP_FCMPG)); } public CompactCodeAttributeComposer dcmpl() { return appendInstruction(new SimpleInstruction(Instruction.OP_DCMPL)); } public CompactCodeAttributeComposer dcmpg() { return appendInstruction(new SimpleInstruction(Instruction.OP_DCMPG)); } public CompactCodeAttributeComposer ifeq(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFEQ, branchLabel.offset)); } public CompactCodeAttributeComposer ifne(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFNE, branchLabel.offset)); } public CompactCodeAttributeComposer iflt(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFLT, branchLabel.offset)); } public CompactCodeAttributeComposer ifge(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFGE, branchLabel.offset)); } public CompactCodeAttributeComposer ifgt(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFGT, branchLabel.offset)); } public CompactCodeAttributeComposer ifle(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFLE, branchLabel.offset)); } public CompactCodeAttributeComposer ificmpeq(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFICMPEQ, branchLabel.offset)); } public CompactCodeAttributeComposer ificmpne(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFICMPNE, branchLabel.offset)); } public CompactCodeAttributeComposer ificmplt(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFICMPLT, branchLabel.offset)); } public CompactCodeAttributeComposer ificmpge(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFICMPGE, branchLabel.offset)); } public CompactCodeAttributeComposer ificmpgt(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFICMPGT, branchLabel.offset)); } public CompactCodeAttributeComposer ificmple(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFICMPLE, branchLabel.offset)); } public CompactCodeAttributeComposer ifacmpeq(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFACMPEQ, branchLabel.offset)); } public CompactCodeAttributeComposer ifacmpne(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFACMPNE, branchLabel.offset)); } public CompactCodeAttributeComposer goto_(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_GOTO, branchLabel.offset)); } public CompactCodeAttributeComposer jsr(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_JSR, branchLabel.offset)); } public CompactCodeAttributeComposer ret(int variableIndex) { return appendInstruction(new VariableInstruction(Instruction.OP_RET, variableIndex)); } public CompactCodeAttributeComposer tableswitch( Label defaultLabel, int lowCase, int highCase, Label[] jumpLabels) { return appendInstruction( new TableSwitchInstruction( Instruction.OP_TABLESWITCH, defaultLabel.offset, lowCase, highCase, offsets(jumpLabels))); } public CompactCodeAttributeComposer lookupswitch( Label defaultLabel, int[] cases, Label[] jumpLabels) { return appendInstruction( new LookUpSwitchInstruction( Instruction.OP_LOOKUPSWITCH, defaultLabel.offset, cases, offsets(jumpLabels))); } public CompactCodeAttributeComposer ireturn() { return appendInstruction(new SimpleInstruction(Instruction.OP_IRETURN)); } public CompactCodeAttributeComposer lreturn() { return appendInstruction(new SimpleInstruction(Instruction.OP_LRETURN)); } public CompactCodeAttributeComposer freturn() { return appendInstruction(new SimpleInstruction(Instruction.OP_FRETURN)); } public CompactCodeAttributeComposer dreturn() { return appendInstruction(new SimpleInstruction(Instruction.OP_DRETURN)); } public CompactCodeAttributeComposer areturn() { return appendInstruction(new SimpleInstruction(Instruction.OP_ARETURN)); } public CompactCodeAttributeComposer return_() { return appendInstruction(new SimpleInstruction(Instruction.OP_RETURN)); } public CompactCodeAttributeComposer getstatic(Clazz clazz, Field field) { return getstatic( clazz.getName(), field.getName(clazz), field.getDescriptor(clazz), clazz, field); } public CompactCodeAttributeComposer getstatic(String className, String name, String descriptor) { return getstatic(className, name, descriptor, null, null); } public CompactCodeAttributeComposer getstatic( String className, String name, String descriptor, Clazz referencedClass, Field referencedField) { return getstatic( constantPoolEditor.addFieldrefConstant( className, name, descriptor, referencedClass, referencedField)); } public CompactCodeAttributeComposer getstatic(int constantIndex) { return appendInstruction(new ConstantInstruction(Instruction.OP_GETSTATIC, constantIndex)); } public CompactCodeAttributeComposer putstatic(Clazz referencedClass, Field referencedField) { return putstatic( referencedClass.getName(), referencedField.getName(referencedClass), referencedField.getDescriptor(referencedClass), referencedClass, referencedField); } public CompactCodeAttributeComposer putstatic(String className, String name, String descriptor) { return putstatic(className, name, descriptor, null, null); } public CompactCodeAttributeComposer putstatic( String className, String name, String descriptor, Clazz referencedClass, Field referencedField) { return putstatic( constantPoolEditor.addFieldrefConstant( className, name, descriptor, referencedClass, referencedField)); } public CompactCodeAttributeComposer putstatic(int constantIndex) { return appendInstruction(new ConstantInstruction(Instruction.OP_PUTSTATIC, constantIndex)); } public CompactCodeAttributeComposer getfield(Clazz clazz, Field field) { return getfield( clazz.getName(), field.getName(clazz), field.getDescriptor(clazz), clazz, field); } public CompactCodeAttributeComposer getfield(String className, String name, String descriptor) { return getfield(className, name, descriptor, null, null); } public CompactCodeAttributeComposer getfield( String className, String name, String descriptor, Clazz referencedClass, Field referencedField) { return getfield( constantPoolEditor.addFieldrefConstant( className, name, descriptor, referencedClass, referencedField)); } public CompactCodeAttributeComposer getfield(int constantIndex) { return appendInstruction(new ConstantInstruction(Instruction.OP_GETFIELD, constantIndex)); } public CompactCodeAttributeComposer putfield(Clazz clazz, Field field) { return putfield( clazz.getName(), field.getName(clazz), field.getDescriptor(clazz), clazz, field); } public CompactCodeAttributeComposer putfield(String className, String name, String descriptor) { return putfield(className, name, descriptor, null, null); } public CompactCodeAttributeComposer putfield( String className, String name, String descriptor, Clazz referencedClass, Field referencedField) { return putfield( constantPoolEditor.addFieldrefConstant( className, name, descriptor, referencedClass, referencedField)); } public CompactCodeAttributeComposer putfield(int constantIndex) { return appendInstruction(new ConstantInstruction(Instruction.OP_PUTFIELD, constantIndex)); } public CompactCodeAttributeComposer invokevirtual(Clazz clazz, Method method) { return invokevirtual( clazz.getName(), method.getName(clazz), method.getDescriptor(clazz), clazz, method); } public CompactCodeAttributeComposer invokevirtual( String className, String name, String descriptor) { return invokevirtual(className, name, descriptor, null, null); } public CompactCodeAttributeComposer invokevirtual( String className, String name, String descriptor, Clazz referencedClass, Method referencedMethod) { return invokevirtual( constantPoolEditor.addMethodrefConstant( className, name, descriptor, referencedClass, referencedMethod)); } public CompactCodeAttributeComposer invokevirtual(int constantIndex) { return appendInstruction(new ConstantInstruction(Instruction.OP_INVOKEVIRTUAL, constantIndex)); } public CompactCodeAttributeComposer invokespecial(Clazz clazz, Method method) { return invokespecial( clazz.getName(), method.getName(clazz), method.getDescriptor(clazz), clazz, method); } public CompactCodeAttributeComposer invokespecial( String className, String name, String descriptor) { return invokespecial(className, name, descriptor, null, null); } public CompactCodeAttributeComposer invokespecial( String className, String name, String descriptor, Clazz referencedClass, Method referencedMethod) { return invokespecial( constantPoolEditor.addMethodrefConstant( className, name, descriptor, referencedClass, referencedMethod)); } public CompactCodeAttributeComposer invokespecial(int constantIndex) { return appendInstruction(new ConstantInstruction(Instruction.OP_INVOKESPECIAL, constantIndex)); } public CompactCodeAttributeComposer invokestatic(Clazz clazz, Method method) { return invokestatic( clazz.getName(), method.getName(clazz), method.getDescriptor(clazz), clazz, method); } public CompactCodeAttributeComposer invokestatic( String className, String name, String descriptor) { return invokestatic(className, name, descriptor, null, null); } public CompactCodeAttributeComposer invokestatic( String className, String name, String descriptor, Clazz referencedClass, Method referencedMethod) { return invokestatic( constantPoolEditor.addMethodrefConstant( className, name, descriptor, referencedClass, referencedMethod)); } public CompactCodeAttributeComposer invokestatic_interface(Clazz clazz, Method method) { return invokestatic_interface( clazz.getName(), method.getName(clazz), method.getDescriptor(clazz), clazz, method); } public CompactCodeAttributeComposer invokestatic_interface( String className, String name, String descriptor) { return invokestatic_interface(className, name, descriptor, null, null); } public CompactCodeAttributeComposer invokestatic_interface( String className, String name, String descriptor, Clazz referencedClass, Method referencedMethod) { return invokestatic( constantPoolEditor.addInterfaceMethodrefConstant( className, name, descriptor, referencedClass, referencedMethod)); } public CompactCodeAttributeComposer invokestatic(int constantIndex) { return appendInstruction(new ConstantInstruction(Instruction.OP_INVOKESTATIC, constantIndex)); } public CompactCodeAttributeComposer invokeinterface(Clazz clazz, Method method) { return invokeinterface( clazz.getName(), method.getName(clazz), method.getDescriptor(clazz), clazz, method); } public CompactCodeAttributeComposer invokeinterface( String className, String name, String descriptor) { return invokeinterface(className, name, descriptor, null, null); } public CompactCodeAttributeComposer invokeinterface( String className, String name, String descriptor, Clazz referencedClass, Method referencedMethod) { int invokeinterfaceConstant = (ClassUtil.internalMethodParameterSize(descriptor, false)) << 8; return invokeinterface( constantPoolEditor.addInterfaceMethodrefConstant( className, name, descriptor, referencedClass, referencedMethod), invokeinterfaceConstant); } public CompactCodeAttributeComposer invokeinterface(int constantIndex, int constant) { return appendInstruction( new ConstantInstruction(Instruction.OP_INVOKEINTERFACE, constantIndex, constant)); } public CompactCodeAttributeComposer invokedynamic( int bootStrapMethodIndex, String name, String descriptor, Clazz[] referencedClasses) { return invokedynamic( constantPoolEditor.addInvokeDynamicConstant( bootStrapMethodIndex, name, descriptor, referencedClasses)); } public CompactCodeAttributeComposer invokedynamic(int constantIndex) { return appendInstruction(new ConstantInstruction(Instruction.OP_INVOKEDYNAMIC, constantIndex)); } public CompactCodeAttributeComposer new_(Clazz clazz) { return new_(clazz.getName(), clazz); } public CompactCodeAttributeComposer new_(String className) { return new_(className, null); } public CompactCodeAttributeComposer new_(String className, Clazz referencedClass) { return new_(constantPoolEditor.addClassConstant(className, referencedClass)); } public CompactCodeAttributeComposer new_(int constantIndex) { return appendInstruction(new ConstantInstruction(Instruction.OP_NEW, constantIndex)); } public CompactCodeAttributeComposer newarray(int constant) { return appendInstruction(new SimpleInstruction(Instruction.OP_NEWARRAY, constant)); } public CompactCodeAttributeComposer anewarray(String className, Clazz referencedClass) { return anewarray(constantPoolEditor.addClassConstant(className, referencedClass)); } public CompactCodeAttributeComposer anewarray(int constantIndex) { return appendInstruction(new ConstantInstruction(Instruction.OP_ANEWARRAY, constantIndex)); } public CompactCodeAttributeComposer arraylength() { return appendInstruction(new SimpleInstruction(Instruction.OP_ARRAYLENGTH)); } public CompactCodeAttributeComposer athrow() { return appendInstruction(new SimpleInstruction(Instruction.OP_ATHROW)); } public CompactCodeAttributeComposer checkcast(String className) { return checkcast(className, null); } public CompactCodeAttributeComposer checkcast(String className, Clazz referencedClass) { return checkcast(constantPoolEditor.addClassConstant(className, referencedClass)); } public CompactCodeAttributeComposer checkcast(int constantIndex) { return appendInstruction(new ConstantInstruction(Instruction.OP_CHECKCAST, constantIndex)); } public CompactCodeAttributeComposer instanceof_(String className, Clazz referencedClass) { return instanceof_(constantPoolEditor.addClassConstant(className, referencedClass)); } public CompactCodeAttributeComposer instanceof_(int constantIndex) { return appendInstruction(new ConstantInstruction(Instruction.OP_INSTANCEOF, constantIndex)); } public CompactCodeAttributeComposer monitorenter() { return appendInstruction(new SimpleInstruction(Instruction.OP_MONITORENTER)); } public CompactCodeAttributeComposer monitorexit() { return appendInstruction(new SimpleInstruction(Instruction.OP_MONITOREXIT)); } public CompactCodeAttributeComposer wide() { return appendInstruction(new SimpleInstruction(Instruction.OP_WIDE)); } public CompactCodeAttributeComposer multianewarray( String className, Clazz referencedClass, int dimensions) { return multianewarray( constantPoolEditor.addClassConstant(className, referencedClass), dimensions); } public CompactCodeAttributeComposer multianewarray(int constantIndex, int dimensions) { return appendInstruction( new ConstantInstruction(Instruction.OP_MULTIANEWARRAY, constantIndex, dimensions)); } public CompactCodeAttributeComposer ifnull(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFNULL, branchLabel.offset)); } public CompactCodeAttributeComposer ifnonnull(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_IFNONNULL, branchLabel.offset)); } public CompactCodeAttributeComposer goto_w(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_GOTO_W, branchLabel.offset)); } public CompactCodeAttributeComposer jsr_w(Label branchLabel) { return appendInstruction(new BranchInstruction(Instruction.OP_JSR_W, branchLabel.offset)); } // Additional convenience methods. /** * Pushes the given primitive value on the stack. * *

Operand stack: ... -> ..., value * * @param primitive the primitive value to be pushed - should never be null. * @param internalType the internal type of the primitive ('Z','B','I',...) */ public CompactCodeAttributeComposer pushPrimitive(Object primitive, char internalType) { switch (internalType) { case TypeConstants.BOOLEAN: return ((Boolean) primitive).booleanValue() ? iconst_1() : iconst_0(); case TypeConstants.BYTE: return bipush((Byte) primitive); case TypeConstants.CHAR: return ldc(((Character) primitive).charValue()); case TypeConstants.SHORT: return sipush((Short) primitive); case TypeConstants.INT: return ldc(((Integer) primitive).intValue()); case TypeConstants.LONG: return ldc2_w((Long) primitive); case TypeConstants.FLOAT: return ldc(((Float) primitive).floatValue()); case TypeConstants.DOUBLE: return ldc2_w((Double) primitive); default: throw new IllegalArgumentException(primitive.toString()); } } /** * Pushes the given primitive int on the stack in the most efficient way (as an iconst, bipush, * sipush, or ldc instruction). * * @param value the int value to be pushed. */ public CompactCodeAttributeComposer pushInt(int value) { switch (value) { case -1: return iconst_m1(); case 0: return iconst_0(); case 1: return iconst_1(); case 2: return iconst_2(); case 3: return iconst_3(); case 4: return iconst_4(); case 5: return iconst_5(); default: return value == (byte) value ? bipush(value) : value == (short) value ? sipush(value) : ldc(value); } } /** * Pushes the given primitive float on the stack in the most efficient way (as an fconst or ldc * instruction). * * @param value the float value to be pushed. */ public CompactCodeAttributeComposer pushFloat(float value) { return value == 0f ? fconst_0() : value == 1f ? fconst_1() : value == 2f ? fconst_2() : ldc(value); } /** * Pushes the given primitive long on the stack in the most efficient way (as an lconst or ldc * instruction). * * @param value the long value to be pushed. */ public CompactCodeAttributeComposer pushLong(long value) { return value == 0L ? lconst_0() : value == 1L ? lconst_1() : ldc2_w(value); } /** * Pushes the given primitive double on the stack in the most efficient way (as a dconst or ldc * instruction). * * @param value the double value to be pushed. */ public CompactCodeAttributeComposer pushDouble(double value) { return value == 0. ? dconst_0() : value == 1. ? dconst_1() : ldc2_w(value); } /** * Pushes a new array on the stack. * *

Operand stack: ... -> ..., array * * @param elementTypeOrClassName the array element type (or class name in case of objects). * @param size the size of the array to be created. */ public CompactCodeAttributeComposer pushNewArray(String elementTypeOrClassName, int size) { // Create new array. pushInt(size); return ClassUtil.isInternalPrimitiveType(elementTypeOrClassName) ? newarray(InstructionUtil.arrayTypeFromInternalType(elementTypeOrClassName.charAt(0))) : anewarray(elementTypeOrClassName, null); } /** * Loads the given variable onto the stack. * *

Operand stack: ... -> ..., value * * @param variableIndex the index of the variable to be loaded. * @param internalType the type of the variable to be loaded. */ public CompactCodeAttributeComposer load(int variableIndex, String internalType) { return load(variableIndex, internalType.charAt(0)); } /** * Loads the given variable of primitive type onto the stack. * *

Operand stack: ... -> ..., value * * @param variableIndex the index of the variable to be loaded. * @param internalType the primitive type of the variable to be loaded. */ public CompactCodeAttributeComposer load(int variableIndex, char internalType) { switch (internalType) { case TypeConstants.BOOLEAN: case TypeConstants.BYTE: case TypeConstants.CHAR: case TypeConstants.SHORT: case TypeConstants.INT: return iload(variableIndex); case TypeConstants.LONG: return lload(variableIndex); case TypeConstants.FLOAT: return fload(variableIndex); case TypeConstants.DOUBLE: return dload(variableIndex); default: return aload(variableIndex); } } /** * Stores the value on top of the stack in the variable with given index. * *

Operand stsack: ..., value -> ... * * @param variableIndex the index of the variable where to store the value. * @param internalType the type of the value to be stored. */ public CompactCodeAttributeComposer store(int variableIndex, String internalType) { return store(variableIndex, internalType.charAt(0)); } /** * Stores the primitve value on top of the stack in the variable with given index. * *

Operand stack: ..., value -> ... * * @param variableIndex the index of the variable where to store the value. * @param internalType the primitive type of the value to be stored. */ public CompactCodeAttributeComposer store(int variableIndex, char internalType) { switch (internalType) { case TypeConstants.BOOLEAN: case TypeConstants.BYTE: case TypeConstants.CHAR: case TypeConstants.SHORT: case TypeConstants.INT: return istore(variableIndex); case TypeConstants.LONG: return lstore(variableIndex); case TypeConstants.FLOAT: return fstore(variableIndex); case TypeConstants.DOUBLE: return dstore(variableIndex); default: return astore(variableIndex); } } /** * Stores an element to an array. * *

Operand stack: ..., array, index, value -> ... * * @param elementType the type of the value to be stored. */ public CompactCodeAttributeComposer storeToArray(String elementType) { switch (elementType.charAt(0)) { case TypeConstants.BOOLEAN: case TypeConstants.BYTE: return bastore(); case TypeConstants.CHAR: return castore(); case TypeConstants.SHORT: return sastore(); case TypeConstants.INT: return iastore(); case TypeConstants.LONG: return lastore(); case TypeConstants.FLOAT: return fastore(); case TypeConstants.DOUBLE: return dastore(); default: return aastore(); } } /** * Appends the proper return statement for the given internal type. * * @param internalType the return type. */ public CompactCodeAttributeComposer return_(String internalType) { switch (internalType.charAt(0)) { case TypeConstants.BOOLEAN: case TypeConstants.BYTE: case TypeConstants.CHAR: case TypeConstants.SHORT: case TypeConstants.INT: return ireturn(); case TypeConstants.LONG: return lreturn(); case TypeConstants.FLOAT: return freturn(); case TypeConstants.DOUBLE: return dreturn(); case TypeConstants.VOID: return return_(); default: return areturn(); } } /** Appends instructions to print out the given message and the top int on the stack. */ public CompactCodeAttributeComposer appendPrintIntegerInstructions(String message) { return this.appendPrintInstructions(message).appendPrintIntegerInstructions(); } /** * Appends instructions to print out the given message and the top int on the stack as a * hexadecimal value. */ public CompactCodeAttributeComposer appendPrintIntegerHexInstructions(String message) { return this.appendPrintInstructions(message).appendPrintIntegerHexInstructions(); } /** Appends instructions to print out the given message and the top long on the stack. */ public CompactCodeAttributeComposer appendPrintLongInstructions(String message) { return this.appendPrintInstructions(message).appendPrintLongInstructions(); } /** Appends instructions to print out the given message and the top String on the stack. */ public CompactCodeAttributeComposer appendPrintStringInstructions(String message) { return this.appendPrintInstructions(message).appendPrintStringInstructions(); } /** Appends instructions to print out the given message and the top Object on the stack. */ public CompactCodeAttributeComposer appendPrintObjectInstructions(String message) { return this.appendPrintInstructions(message).appendPrintObjectInstructions(); } /** * Appends instructions to print out the given message and the stack trace of the top Throwable on * the stack. */ public CompactCodeAttributeComposer appendPrintStackTraceInstructions(String message) { return this.appendPrintInstructions(message).appendPrintStackTraceInstructions(); } /** Appends instructions to print out the given message. */ public CompactCodeAttributeComposer appendPrintInstructions(String message) { return this.getstatic("java/lang/System", "err", "Ljava/io/PrintStream;") .ldc(message) .invokevirtual("java/io/PrintStream", "println", "(Ljava/lang/String;)V"); } /** Appends instructions to print out the top int on the stack. */ public CompactCodeAttributeComposer appendPrintIntegerInstructions() { return this.dup() .getstatic("java/lang/System", "err", "Ljava/io/PrintStream;") .swap() .invokevirtual("java/io/PrintStream", "println", "(I)V"); } /** Appends instructions to print out the top integer on the stack as a hexadecimal value. */ public CompactCodeAttributeComposer appendPrintIntegerHexInstructions() { return this.dup() .getstatic("java/lang/System", "err", "Ljava/io/PrintStream;") .swap() .invokestatic("java/lang/Integer", "toHexString", "(I)Ljava/lang/String;") .invokevirtual("java/io/PrintStream", "println", "(Ljava/lang/String;)V"); } /** Appends instructions to print out the top long on the stack. */ public CompactCodeAttributeComposer appendPrintLongInstructions() { return this.dup2() .getstatic("java/lang/System", "err", "Ljava/io/PrintStream;") .dup_x2() .pop() .invokevirtual("java/io/PrintStream", "println", "(J)V"); } /** Appends instructions to print out the top String on the stack. */ public CompactCodeAttributeComposer appendPrintStringInstructions() { return this.dup() .getstatic("java/lang/System", "err", "Ljava/io/PrintStream;") .swap() .invokevirtual("java/io/PrintStream", "println", "(Ljava/lang/String;)V"); } /** Appends instructions to print out the top Object on the stack. */ public CompactCodeAttributeComposer appendPrintObjectInstructions() { return this.dup() .getstatic("java/lang/System", "err", "Ljava/io/PrintStream;") .swap() .invokevirtual("java/io/PrintStream", "println", "(Ljava/lang/Object;)V"); } /** Appends instructions to print out the stack trace of the top Throwable on the stack. */ public CompactCodeAttributeComposer appendPrintStackTraceInstructions() { return this.dup().invokevirtual("java/lang/Throwable", "printStackTrace", "()V"); } /** Adds the code that has been built as a code attribute to the given method. */ public void addCodeAttribute(ProgramClass programClass, ProgramMethod programMethod) { codeAttributeComposer.addCodeAttribute(programClass, programMethod, constantPoolEditor); } // Implementations for AttributeVisitor. public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} /** Sets the code that has been built in the given code attribute. */ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) { codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute); } // Small utility methods. /** Returns the offsets of the given labels. */ private int[] offsets(Label[] labels) { int[] offsets = new int[labels.length]; for (int index = 0; index < offsets.length; index++) { offsets[index] = labels[index].offset; } return offsets; } /** * This class represents a label to which branch instructions and switch instructions can jump. */ public class Label { private final int offset; private Label(int offset) { this.offset = offset; } } /** Small sample application that illustrates the use of this class. */ public static void main(String[] args) { // Create an empty class. ProgramClass programClass = new ProgramClass( VersionConstants.CLASS_VERSION_1_8, 1, new Constant[10], AccessConstants.PUBLIC, 0, 0); // Add its name and superclass. ConstantPoolEditor constantPoolEditor = new ConstantPoolEditor(programClass); programClass.u2thisClass = constantPoolEditor.addClassConstant("com/example/Test", programClass); programClass.u2superClass = constantPoolEditor.addClassConstant(ClassConstants.NAME_JAVA_LANG_OBJECT, null); // Create an empty method. ProgramMethod programMethod = new ProgramMethod( AccessConstants.PUBLIC, constantPoolEditor.addUtf8Constant("test"), constantPoolEditor.addUtf8Constant("()I"), null); // Add the method to the class. ClassEditor classEditor = new ClassEditor(programClass); classEditor.addMethod(programMethod); // Compose the code -- the equivalent of this java code: // try // { // if (1 < 2) return 1; else return 2; // } // catch (Exception e) // { // return -1; // } CompactCodeAttributeComposer composer = new CompactCodeAttributeComposer(programClass); final Label TRY_START = composer.createLabel(); final Label TRY_END = composer.createLabel(); final Label ELSE = composer.createLabel(); composer .beginCodeFragment(50) .label(TRY_START) .iconst_1() .iconst_2() .ificmplt(ELSE) .iconst_1() .ireturn() .label(ELSE) .iconst_2() .ireturn() .label(TRY_END) .catch_(TRY_START, TRY_END, "java/lang/Exception", null) .iconst_m1() .ireturn() .endCodeFragment(); // Add the code as a code attribute to the given method. composer.addCodeAttribute(programClass, programMethod); // Print out the result. programClass.accept(new ClassPrinter()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy