Search in sources :

Example 6 with MethodWriterImpl

use of dyvilx.tools.compiler.backend.MethodWriterImpl in project Dyvil by Dyvil.

the class CodeClass method write.

@Override
public void write(ClassWriter writer) throws BytecodeException {
    // Header
    String signature = this.getSignature();
    String superClass = null;
    String[] interfaces = this.getInterfaceArray();
    if (this.superType != null) {
        superClass = this.superType.getInternalName();
    }
    final long flags = ModifierUtil.getFlags(this);
    int modifiers = ModifierUtil.getJavaModifiers(flags);
    if ((modifiers & Modifiers.INTERFACE) == 0) {
        modifiers |= ASMConstants.ACC_SUPER;
    }
    writer.visit(ClassFormat.CLASS_VERSION, modifiers, this.getInternalName(), signature, superClass, interfaces);
    // Source
    writer.visitSource(this.getHeader().getName() + DyvilFileType.DYVIL_EXTENSION, null);
    if (this.enclosingClass != null) {
        this.writeInnerClassInfo(writer);
    }
    // Annotations
    this.writeAnnotations(writer, flags);
    if (this.superType != null) {
        IClass iclass = this.superType.getTheClass();
        if (iclass != null) {
            iclass.writeInnerClassInfo(writer);
        }
    }
    if (this.interfaces != null) {
        for (IType type : this.interfaces) {
            final IClass iclass = type.getTheClass();
            if (iclass != null) {
                iclass.writeInnerClassInfo(writer);
            }
        }
    }
    // Compute Trait Classes
    final Set<IClass> traitClasses;
    if ((modifiers & Modifiers.INTERFACE) == 0) {
        traitClasses = new ArraySet<>();
        this.traitInit = !fillTraitClasses(this, traitClasses, true) && !traitClasses.isEmpty();
    } else {
        traitClasses = null;
    }
    for (int i = 0; i < this.compilableCount; i++) {
        this.compilables[i].write(writer);
    }
    this.metadata.write(writer);
    this.writeClassParameters(writer);
    if (this.body != null) {
        this.body.write(writer);
    }
    this.metadata.writePost(writer);
    // Create the static <clinit> method
    MethodWriter initWriter = new MethodWriterImpl(writer, writer.visitMethod(Modifiers.STATIC, "<clinit>", "()V", null, null));
    initWriter.visitCode();
    this.writeStaticInit(initWriter);
    initWriter.visitEnd(Types.VOID);
    if (traitClasses == null || traitClasses.isEmpty()) {
        return;
    }
    // Create the virtual <traitinit> method
    initWriter = new MethodWriterImpl(writer, writer.visitMethod(Modifiers.PROTECTED, TraitMetadata.INIT_NAME, "()V", null, null));
    initWriter.visitCode();
    initWriter.setLocalType(0, this.getInternalName());
    for (IClass traitClass : traitClasses) {
        final String internal = traitClass.getInternalName();
        // Load 'this'
        initWriter.visitVarInsn(Opcodes.ALOAD, 0);
        // Invoke the static <traitinit> method of the trait class
        initWriter.visitMethodInsn(Opcodes.INVOKESTATIC, internal, TraitMetadata.INIT_NAME, "(L" + internal + ";)V", true);
    }
    initWriter.visitInsn(Opcodes.RETURN);
    initWriter.visitEnd();
}
Also used : MethodWriterImpl(dyvilx.tools.compiler.backend.MethodWriterImpl) MethodWriter(dyvilx.tools.compiler.backend.MethodWriter) IType(dyvilx.tools.compiler.ast.type.IType)

Example 7 with MethodWriterImpl

use of dyvilx.tools.compiler.backend.MethodWriterImpl in project Dyvil by Dyvil.

the class CodeConstructor method write.

@Override
public void write(ClassWriter writer) throws BytecodeException {
    final long flags = ModifierUtil.getFlags(this);
    final MethodWriter methodWriter = new MethodWriterImpl(writer, writer.visitMethod(ModifierUtil.getJavaModifiers(flags), "<init>", this.getDescriptor(), this.getSignature(), this.getInternalExceptions()));
    // Write Modifiers and Annotations
    ModifierUtil.writeModifiers(methodWriter, flags);
    this.attributes.write(methodWriter);
    if (this.hasModifier(Modifiers.DEPRECATED) && this.getAnnotation(Deprecation.DEPRECATED_CLASS) == null) {
        methodWriter.visitAnnotation(Deprecation.DYVIL_EXTENDED, true).visitEnd();
    }
    // Write Parameters
    methodWriter.setThisType(this.enclosingClass.getInternalName());
    this.parameters.write(methodWriter);
    // Write Code
    final Label start = new Label();
    final Label end = new Label();
    methodWriter.visitCode();
    methodWriter.visitLabel(start);
    if (this.initializerCall != null) {
        this.initializerCall.writeExpression(methodWriter, Types.VOID);
    }
    if (this.initializerCall == null || this.initializerCall.isSuper()) {
        this.enclosingClass.writeClassInit(methodWriter);
    }
    if (this.value != null) {
        this.value.writeExpression(methodWriter, Types.VOID);
    }
    methodWriter.visitLabel(end);
    methodWriter.visitEnd(Types.VOID);
    // Write Local Variable Data
    methodWriter.visitLocalVariable("this", 'L' + this.enclosingClass.getInternalName() + ';', null, start, end, 0);
    this.parameters.writeLocals(methodWriter, start, end);
}
Also used : MethodWriterImpl(dyvilx.tools.compiler.backend.MethodWriterImpl) MethodWriter(dyvilx.tools.compiler.backend.MethodWriter) Label(dyvilx.tools.asm.Label)

Example 8 with MethodWriterImpl

use of dyvilx.tools.compiler.backend.MethodWriterImpl in project Dyvil by Dyvil.

the class IParameter method writeDefaultValue.

default void writeDefaultValue(ClassWriter writer) {
    final IValue value = this.getValue();
    assert value != null;
    final ICallableMember method = this.getMethod();
    final IType type = this.getType();
    final String name;
    final int access;
    if (method == null) {
        name = "init$paramDefault$" + this.getInternalName();
        access = Modifiers.STATIC;
    } else {
        name = method.getInternalName() + "$paramDefault$" + this.getInternalName();
        access = (method.getAttributes().flags() & Modifiers.MEMBER_MODIFIERS) | Modifiers.STATIC;
    }
    final String desc = "()" + this.getDescriptor();
    final String signature = "()" + this.getSignature();
    final MethodWriter mw = new MethodWriterImpl(writer, writer.visitMethod(access, name, desc, signature, null));
    mw.visitCode();
    value.writeExpression(mw, type);
    mw.visitEnd(type);
}
Also used : IValue(dyvilx.tools.compiler.ast.expression.IValue) MethodWriterImpl(dyvilx.tools.compiler.backend.MethodWriterImpl) MethodWriter(dyvilx.tools.compiler.backend.MethodWriter) ICallableMember(dyvilx.tools.compiler.ast.method.ICallableMember) IType(dyvilx.tools.compiler.ast.type.IType)

Example 9 with MethodWriterImpl

use of dyvilx.tools.compiler.backend.MethodWriterImpl in project Dyvil by Dyvil.

the class CaseClassMetadata method write.

@Override
public void write(ClassWriter writer) throws BytecodeException {
    super.write(writer);
    MethodWriter mw;
    final String internal = this.theClass.getInternalName();
    if ((this.members & EQUALS) == 0) {
        mw = new MethodWriterImpl(writer, writer.visitMethod(Modifiers.PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null));
        mw.setThisType(internal);
        mw.visitParameter(1, "obj", Types.OBJECT, 0);
        mw.visitCode();
        CaseClasses.writeEquals(mw, this.theClass);
        mw.visitEnd();
    }
    if ((this.members & HASHCODE) == 0) {
        mw = new MethodWriterImpl(writer, writer.visitMethod(Modifiers.PUBLIC, "hashCode", "()I", null, null));
        mw.setThisType(internal);
        mw.visitCode();
        CaseClasses.writeHashCode(mw, this.theClass);
        mw.visitEnd();
    }
    if ((this.members & TOSTRING) == 0) {
        mw = new MethodWriterImpl(writer, writer.visitMethod(Modifiers.PUBLIC, "toString", "()Ljava/lang/String;", null, null));
        mw.setThisType(internal);
        mw.visitCode();
        CaseClasses.writeToString(mw, this.theClass);
        mw.visitEnd();
    }
}
Also used : MethodWriterImpl(dyvilx.tools.compiler.backend.MethodWriterImpl) MethodWriter(dyvilx.tools.compiler.backend.MethodWriter)

Example 10 with MethodWriterImpl

use of dyvilx.tools.compiler.backend.MethodWriterImpl 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();
    }
}
Also used : MethodWriterImpl(dyvilx.tools.compiler.backend.MethodWriterImpl) MethodWriter(dyvilx.tools.compiler.backend.MethodWriter) Label(dyvilx.tools.asm.Label) HashSet(dyvil.collection.mutable.HashSet) IType(dyvilx.tools.compiler.ast.type.IType)

Aggregations

MethodWriterImpl (dyvilx.tools.compiler.backend.MethodWriterImpl)10 MethodWriter (dyvilx.tools.compiler.backend.MethodWriter)9 Label (dyvilx.tools.asm.Label)4 IType (dyvilx.tools.compiler.ast.type.IType)3 HashSet (dyvil.collection.mutable.HashSet)1 FieldVisitor (dyvilx.tools.asm.FieldVisitor)1 IConstructor (dyvilx.tools.compiler.ast.constructor.IConstructor)1 IValue (dyvilx.tools.compiler.ast.expression.IValue)1 CaptureField (dyvilx.tools.compiler.ast.field.capture.CaptureField)1 ICallableMember (dyvilx.tools.compiler.ast.method.ICallableMember)1 ParameterList (dyvilx.tools.compiler.ast.parameter.ParameterList)1