use of dyvilx.tools.compiler.backend.MethodWriter in project Dyvil by Dyvil.
the class CodeMethod method write.
@Override
public void write(ClassWriter writer) throws BytecodeException {
final boolean interfaceClass = this.enclosingClass.isInterface();
final long flags = ModifierUtil.getFlags(this);
final String ownerClassName = this.enclosingClass.getInternalName();
final String mangledName = this.getInternalName();
final String descriptor = this.getDescriptor();
final String signature = this.needsSignature() ? this.getSignature() : null;
final String[] exceptionTypes = this.getInternalExceptions();
MethodWriter methodWriter = new MethodWriterImpl(writer, writer.visitMethod(ModifierUtil.getJavaModifiers(flags), mangledName, descriptor, signature, exceptionTypes));
if (!this.isStatic()) {
methodWriter.setThisType(ownerClassName);
}
this.writeAnnotations(methodWriter, flags);
this.writeParameters(methodWriter);
final Label start = new Label();
final Label end = new Label();
if (this.value != null) {
methodWriter.visitCode();
methodWriter.visitLabel(start);
this.value.writeExpression(methodWriter, this.type);
methodWriter.visitLabel(end);
methodWriter.visitEnd(this.type);
} else if (this.hasModifier(Modifiers.STATIC | Modifiers.ABSTRACT)) {
// no value, but no abstract flag
methodWriter.visitCode();
methodWriter.visitTypeInsn(Opcodes.NEW, "java/lang/AbstractMethodError");
methodWriter.visitInsn(Opcodes.DUP);
methodWriter.visitLdcInsn(ClassFormat.internalToPackage(ownerClassName) + '.' + mangledName + descriptor);
methodWriter.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/AbstractMethodError", "<init>", "(Ljava/lang/String;)V", false);
methodWriter.visitInsn(Opcodes.ATHROW);
methodWriter.visitEnd(this.type);
}
if (!this.isStatic()) {
methodWriter.visitLocalVariable("this", 'L' + ownerClassName + ';', null, start, end, 0);
}
this.parameters.writeLocals(methodWriter, start, end);
if (this.overrideMethods == null) {
return;
}
final int lineNumber = this.lineNumber();
final int opcode = this.getInvokeOpcode();
final int bridgeModifiers = Modifiers.PUBLIC | Modifiers.SYNTHETIC | Modifiers.BRIDGE | (this.isStatic() ? Modifiers.STATIC : 0);
/*
* Contains entries in the format 'mangledName(paramTypes)returnType'
* Used to ensure unique bridge methods
*/
final Set<String> descriptors = new HashSet<>(1 + this.overrideMethods.size());
descriptors.add(mangledName + descriptor);
for (IMethod overrideMethod : this.overrideMethods) {
final String overrideDescriptor = overrideMethod.getDescriptor();
final String overrideMangledName = overrideMethod.getInternalName();
final String overrideEntry = overrideMangledName + overrideDescriptor;
// generated
if (descriptors.contains(overrideEntry)) {
continue;
}
descriptors.add(overrideEntry);
// Generate a bridge method
methodWriter = new MethodWriterImpl(writer, writer.visitMethod(bridgeModifiers, overrideMangledName, overrideDescriptor, null, exceptionTypes));
methodWriter.visitCode();
if (!this.isStatic()) {
methodWriter.setThisType(ownerClassName);
methodWriter.visitVarInsn(Opcodes.ALOAD, 0);
}
// Generate Parameters and load arguments
this.writeBridgeParameters(methodWriter, overrideMethod);
// Generate Type Parameters and load reified type arguments
this.writeBridgeTypeParameters(methodWriter, overrideMethod);
final IType overrideReturnType = overrideMethod.getType();
methodWriter.visitLineNumber(lineNumber);
methodWriter.visitMethodInsn(opcode, ownerClassName, mangledName, descriptor, interfaceClass);
this.type.writeCast(methodWriter, overrideReturnType, lineNumber);
methodWriter.visitInsn(overrideReturnType.getReturnOpcode());
methodWriter.visitEnd();
}
}
Aggregations