Search in sources :

Example 11 with Label

use of dyvilx.tools.asm.Label in project Dyvil by Dyvil.

the class CaseClasses method writeHashCode.

public static void writeHashCode(MethodWriter writer, IType type) throws BytecodeException {
    if (type.isPrimitive()) {
        switch(type.getTypecode()) {
            case PrimitiveType.BOOLEAN_CODE:
                {
                    // Write boolean hashing by using 1231 if the value is true and
                    // 1237 if the value is false
                    Label elseLabel = new Label();
                    Label endLabel = new Label();
                    // if
                    writer.visitJumpInsn(IFEQ, elseLabel);
                    // then
                    writer.visitLdcInsn(1231);
                    writer.visitJumpInsn(GOTO, endLabel);
                    // else
                    writer.visitLabel(elseLabel);
                    writer.visitLdcInsn(1237);
                    writer.visitLabel(endLabel);
                    return;
                }
            case PrimitiveType.BYTE_CODE:
                return;
            case PrimitiveType.SHORT_CODE:
                return;
            case PrimitiveType.CHAR_CODE:
                return;
            case PrimitiveType.INT_CODE:
                return;
            case PrimitiveType.LONG_CODE:
                // Write a long hashing snippet by XORing the value by the value
                // bit-shifted 32 bits to the right, and then converting the
                // result to an integer. l1 = (int) (l ^ (l >>> 32))
                writer.visitInsn(DUP2);
                writer.visitLdcInsn(32);
                writer.visitInsn(LUSHR);
                writer.visitInsn(LOR);
                writer.visitInsn(L2I);
                return;
            case PrimitiveType.FLOAT_CODE:
                // Write a float hashing snippet using Float.floatToIntBits
                writer.visitLineNumber(0);
                writer.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "floatToIntBits", "(F)I", false);
                return;
            case PrimitiveType.DOUBLE_CODE:
                // Write a double hashing snippet using Double.doubleToLongBits
                // and long hashing
                writer.visitLineNumber(0);
                writer.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "doubleToLongBits", "(D)J", false);
                writer.visitInsn(DUP2);
                writer.visitLdcInsn(32);
                writer.visitInsn(LUSHR);
                writer.visitInsn(LOR);
                writer.visitInsn(L2I);
                return;
        }
    }
    Label elseLabel = new Label();
    Label endLabel = new Label();
    // Write an Object hashing snippet
    // if
    writer.visitInsn(DUP);
    writer.visitJumpInsn(IFNULL, elseLabel);
    // then
    writer.visitLineNumber(0);
    final ArrayType arrayType = type.extract(ArrayType.class);
    if (arrayType != null) {
        writeArrayHashCode(writer, arrayType.getElementType());
    } else {
        writer.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "hashCode", "()I", false);
    }
    writer.visitJumpInsn(GOTO, endLabel);
    // else
    writer.visitLabel(elseLabel);
    writer.visitInsn(POP);
    writer.visitLdcInsn(0);
    writer.visitLabel(endLabel);
}
Also used : ArrayType(dyvilx.tools.compiler.ast.type.compound.ArrayType) Label(dyvilx.tools.asm.Label)

Example 12 with Label

use of dyvilx.tools.asm.Label in project Dyvil by Dyvil.

the class MatchExpr method generateBranched.

private void generateBranched(MethodWriter writer, Object frameType) throws BytecodeException {
    final boolean expr = frameType != null;
    final int localCount = writer.localCount();
    final IType matchedType = this.matchedValue.getType();
    final int varIndex = this.matchedValue.writeStore(writer, null);
    final int localCountInner = writer.localCount();
    Label elseLabel = new Label();
    Label endLabel = new Label();
    for (int i = 0; ; ) {
        MatchCase c = this.cases[i];
        IValue condition = c.condition;
        c.pattern.writeJumpOnMismatch(writer, varIndex, elseLabel);
        if (condition != null) {
            condition.writeInvJump(writer, elseLabel);
        }
        this.writeAction(writer, expr, frameType, c.action);
        writer.resetLocals(localCountInner);
        if (!writer.hasReturn()) {
            writer.visitJumpInsn(Opcodes.GOTO, endLabel);
        }
        writer.visitTargetLabel(elseLabel);
        if (++i < this.caseCount) {
            elseLabel = new Label();
        } else {
            break;
        }
    }
    // MatchError
    writer.visitLabel(elseLabel);
    if (!this.exhaustive) {
        this.writeMatchError(writer, varIndex, matchedType);
    }
    writer.visitLabel(endLabel);
    writer.resetLocals(localCount);
}
Also used : Label(dyvilx.tools.asm.Label) IType(dyvilx.tools.compiler.ast.type.IType)

Example 13 with Label

use of dyvilx.tools.asm.Label in project Dyvil by Dyvil.

the class BooleanOperator method writeExpression.

protected static void writeExpression(MethodWriter writer, IValue value, IType type) {
    final Label label = new Label();
    final Label end = new Label();
    // if (expr) {
    value.writeInvJump(writer, label);
    // true
    writer.visitLdcInsn(1);
    // }
    writer.visitJumpInsn(Opcodes.GOTO, end);
    // else {
    writer.visitLabel(label);
    // false
    writer.visitLdcInsn(0);
    // }
    writer.visitLabel(end);
    if (type != null) {
        Types.BOOLEAN.writeCast(writer, type, value.lineNumber());
    }
}
Also used : Label(dyvilx.tools.asm.Label)

Example 14 with Label

use of dyvilx.tools.asm.Label 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)

Example 15 with Label

use of dyvilx.tools.asm.Label in project Dyvil by Dyvil.

the class OrPattern method writeJumpOnMismatch.

@Override
public void writeJumpOnMismatch(MethodWriter writer, int varIndex, Label target) throws BytecodeException {
    final int locals = writer.localCount();
    varIndex = Pattern.ensureVar(writer, varIndex);
    final Label targetLabel = new Label();
    this.left.writeJumpOnMatch(writer, varIndex, targetLabel);
    writer.resetLocals(locals);
    this.right.writeJumpOnMismatch(writer, varIndex, target);
    writer.visitLabel(targetLabel);
    writer.resetLocals(locals);
}
Also used : Label(dyvilx.tools.asm.Label)

Aggregations

Label (dyvilx.tools.asm.Label)16 MethodWriterImpl (dyvilx.tools.compiler.backend.MethodWriterImpl)4 IType (dyvilx.tools.compiler.ast.type.IType)3 MethodWriter (dyvilx.tools.compiler.backend.MethodWriter)3 Nullable (dyvil.annotation.internal.Nullable)1 HashSet (dyvil.collection.mutable.HashSet)1 FieldVisitor (dyvilx.tools.asm.FieldVisitor)1 ParameterList (dyvilx.tools.compiler.ast.parameter.ParameterList)1 Pattern (dyvilx.tools.compiler.ast.pattern.Pattern)1 ArrayType (dyvilx.tools.compiler.ast.type.compound.ArrayType)1