Search in sources :

Example 11 with BytecodeMethodSignature

use of de.mirkosertic.bytecoder.core.BytecodeMethodSignature in project Bytecoder by mirkosertic.

the class OpenCLCompileBackend method generateCodeFor.

@Override
public OpenCLCompileResult generateCodeFor(CompileOptions aOptions, BytecodeLinkerContext aLinkerContext, Class aEntryPointClass, String aEntryPointMethodName, BytecodeMethodSignature aEntryPointSignatue) {
    BytecodeLinkerContext theLinkerContext = new BytecodeLinkerContext(loader, aOptions.getLogger());
    BytecodeLinkedClass theKernelClass = theLinkerContext.resolveClass(BytecodeObjectTypeRef.fromRuntimeClass(aEntryPointClass));
    theKernelClass.resolveVirtualMethod(aEntryPointMethodName, aEntryPointSignatue);
    BytecodeResolvedMethods theMethodMap = theKernelClass.resolvedMethods();
    StringWriter theStrWriter = new StringWriter();
    OpenCLInputOutputs theInputOutputs;
    // First of all, we link the kernel method
    BytecodeMethod theKernelMethod = theKernelClass.getBytecodeClass().methodByNameAndSignatureOrNull("processWorkItem", new BytecodeMethodSignature(BytecodePrimitiveTypeRef.VOID, new BytecodeTypeRef[0]));
    ProgramGenerator theGenerator = programGeneratorFactory.createFor(aLinkerContext);
    Program theSSAProgram = theGenerator.generateFrom(theKernelClass.getBytecodeClass(), theKernelMethod);
    // Run optimizer
    aOptions.getOptimizer().optimize(theSSAProgram.getControlFlowGraph(), aLinkerContext);
    // Every member of the kernel class becomes a kernel function argument
    try {
        theInputOutputs = inputOutputsFor(theLinkerContext, theKernelClass, theSSAProgram);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    // And then we ca pass it to the code generator to generate the kernel code
    OpenCLWriter theSSAWriter = new OpenCLWriter(theKernelClass, aOptions, theSSAProgram, "", new PrintWriter(theStrWriter), aLinkerContext, theInputOutputs);
    // We use the relooper here
    Relooper theRelooper = new Relooper();
    theMethodMap.stream().forEach(aMethodMapEntry -> {
        BytecodeMethod theMethod = aMethodMapEntry.getValue();
        if (theMethod.isConstructor()) {
            return;
        }
        if (theMethod != theKernelMethod) {
            Program theSSAProgram1 = theGenerator.generateFrom(aMethodMapEntry.getProvidingClass().getBytecodeClass(), theMethod);
            // Run optimizer
            aOptions.getOptimizer().optimize(theSSAProgram1.getControlFlowGraph(), aLinkerContext);
            // Try to reloop it!
            try {
                Relooper.Block theReloopedBlock = theRelooper.reloop(theSSAProgram1.getControlFlowGraph());
                theSSAWriter.printReloopedInline(theMethod, theSSAProgram1, theReloopedBlock);
            } catch (Exception e) {
                throw new IllegalStateException("Error relooping cfg", e);
            }
        }
    });
    // Finally, we write the kernel method
    try {
        Relooper.Block theReloopedBlock = theRelooper.reloop(theSSAProgram.getControlFlowGraph());
        theSSAWriter.printReloopedKernel(theSSAProgram, theReloopedBlock);
    } catch (Exception e) {
        throw new IllegalStateException("Error relooping cfg", e);
    }
    return new OpenCLCompileResult(theInputOutputs, theStrWriter.toString());
}
Also used : Program(de.mirkosertic.bytecoder.ssa.Program) BytecodeMethodSignature(de.mirkosertic.bytecoder.core.BytecodeMethodSignature) BytecodeMethod(de.mirkosertic.bytecoder.core.BytecodeMethod) NaiveProgramGenerator(de.mirkosertic.bytecoder.ssa.NaiveProgramGenerator) ProgramGenerator(de.mirkosertic.bytecoder.ssa.ProgramGenerator) BytecodeTypeRef(de.mirkosertic.bytecoder.core.BytecodeTypeRef) BytecodeResolvedMethods(de.mirkosertic.bytecoder.core.BytecodeResolvedMethods) StringWriter(java.io.StringWriter) Relooper(de.mirkosertic.bytecoder.relooper.Relooper) BytecodeLinkerContext(de.mirkosertic.bytecoder.core.BytecodeLinkerContext) BytecodeLinkedClass(de.mirkosertic.bytecoder.core.BytecodeLinkedClass) PrintWriter(java.io.PrintWriter)

Example 12 with BytecodeMethodSignature

use of de.mirkosertic.bytecoder.core.BytecodeMethodSignature in project Bytecoder by mirkosertic.

the class OpenCLContext method kernelFor.

private CachedKernel kernelFor(Kernel aKernel) {
    Class theKernelClass = aKernel.getClass();
    CachedKernel theCachedKernel = cachedKernels.get(theKernelClass);
    if (theCachedKernel != null) {
        return theCachedKernel;
    }
    OpenCLCompileResult theResult = ALREADY_COMPILED.get(theKernelClass);
    if (theResult == null) {
        Method theMethod;
        try {
            theMethod = aKernel.getClass().getDeclaredMethod("processWorkItem");
        } catch (Exception e) {
            throw new IllegalArgumentException("Error resolving kernel method", e);
        }
        BytecodeMethodSignature theSignature = backend.signatureFrom(theMethod);
        BytecodeLoader theLoader = new BytecodeLoader(theKernelClass.getClassLoader());
        BytecodeLinkerContext theLinkerContext = new BytecodeLinkerContext(theLoader, compileOptions.getLogger());
        theResult = backend.generateCodeFor(compileOptions, theLinkerContext, aKernel.getClass(), theMethod.getName(), theSignature);
        logger.debug("Generated Kernel code : {}", theResult.getData());
        ALREADY_COMPILED.put(theKernelClass, theResult);
    }
    // Construct the program
    cl_program theCLProgram = clCreateProgramWithSource(context, 1, new String[] { theResult.getData() }, null, null);
    clBuildProgram(theCLProgram, 0, null, null, null, null);
    cl_kernel theKernel = clCreateKernel(theCLProgram, "BytecoderKernel", null);
    CachedKernel theCached = new CachedKernel(theResult.getInputOutputs(), theCLProgram, theKernel);
    cachedKernels.put(theKernelClass, theCached);
    return theCached;
}
Also used : org.jocl.cl_kernel(org.jocl.cl_kernel) BytecodeMethodSignature(de.mirkosertic.bytecoder.core.BytecodeMethodSignature) BytecodeLoader(de.mirkosertic.bytecoder.core.BytecodeLoader) BytecodeLinkerContext(de.mirkosertic.bytecoder.core.BytecodeLinkerContext) org.jocl.cl_program(org.jocl.cl_program) Method(java.lang.reflect.Method)

Example 13 with BytecodeMethodSignature

use of de.mirkosertic.bytecoder.core.BytecodeMethodSignature in project Bytecoder by mirkosertic.

the class OpenCLWriter method printInvokeStatic.

private void printInvokeStatic(InvokeStaticMethodExpression aValue) {
    BytecodeLinkedClass theLinkedClass = linkerContext.resolveClass(aValue.getClassName());
    BytecodeResolvedMethods theMethods = theLinkedClass.resolvedMethods();
    AtomicBoolean theFound = new AtomicBoolean(false);
    theMethods.stream().forEach(aMethodMapsEntry -> {
        BytecodeMethod theMethod = aMethodMapsEntry.getValue();
        if (Objects.equals(theMethod.getName().stringValue(), aValue.getMethodName()) && theMethod.getSignature().metchesExactlyTo(aValue.getSignature())) {
            BytecodeAnnotation theAnnotation = theMethod.getAttributes().getAnnotationByType(OpenCLFunction.class.getName());
            if (theAnnotation == null) {
                throw new IllegalArgumentException("Annotation @OpenCLFunction required for static method " + aValue.getMethodName());
            }
            String theMethodName = theAnnotation.getElementValueByName("value").stringValue();
            BytecodeMethodSignature theSignature = aValue.getSignature();
            print(theMethodName);
            print("(");
            List<Value> theArguments = aValue.incomingDataFlows();
            for (int i = 0; i < theArguments.size(); i++) {
                if (i > 0) {
                    print(",");
                }
                if (!theSignature.getArguments()[i].isPrimitive()) {
                    print("*");
                }
                printValue(theArguments.get(i));
            }
            print(")");
            theFound.set(true);
        }
    });
    if (!theFound.get()) {
        throw new IllegalArgumentException("Not supported method : " + aValue.getMethodName());
    }
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) BytecodeAnnotation(de.mirkosertic.bytecoder.core.BytecodeAnnotation) BytecodeResolvedMethods(de.mirkosertic.bytecoder.core.BytecodeResolvedMethods) BytecodeMethodSignature(de.mirkosertic.bytecoder.core.BytecodeMethodSignature) BytecodeMethod(de.mirkosertic.bytecoder.core.BytecodeMethod) DoubleValue(de.mirkosertic.bytecoder.ssa.DoubleValue) Value(de.mirkosertic.bytecoder.ssa.Value) IntegerValue(de.mirkosertic.bytecoder.ssa.IntegerValue) LongValue(de.mirkosertic.bytecoder.ssa.LongValue) FloatValue(de.mirkosertic.bytecoder.ssa.FloatValue) OpenCLFunction(de.mirkosertic.bytecoder.api.opencl.OpenCLFunction) BytecodeLinkedClass(de.mirkosertic.bytecoder.core.BytecodeLinkedClass)

Example 14 with BytecodeMethodSignature

use of de.mirkosertic.bytecoder.core.BytecodeMethodSignature in project Bytecoder by mirkosertic.

the class WASMSSAWriter method writeNewMultiArrayValue.

private void writeNewMultiArrayValue(NewMultiArrayExpression aValue) {
    List<Value> theDimensions = aValue.incomingDataFlows();
    BytecodeTypeRef theType = aValue.getType();
    String theMethodName;
    switch(theDimensions.size()) {
        case 1:
            theMethodName = WASMWriterUtils.toMethodName(BytecodeObjectTypeRef.fromRuntimeClass(MemoryManager.class), "newArray", new BytecodeMethodSignature(BytecodeObjectTypeRef.fromRuntimeClass(Address.class), new BytecodeTypeRef[] { BytecodePrimitiveTypeRef.INT, BytecodePrimitiveTypeRef.INT, BytecodePrimitiveTypeRef.INT }));
            break;
        case 2:
            theMethodName = WASMWriterUtils.toMethodName(BytecodeObjectTypeRef.fromRuntimeClass(MemoryManager.class), "newArray", new BytecodeMethodSignature(BytecodeObjectTypeRef.fromRuntimeClass(Address.class), new BytecodeTypeRef[] { BytecodePrimitiveTypeRef.INT, BytecodePrimitiveTypeRef.INT, BytecodePrimitiveTypeRef.INT, BytecodePrimitiveTypeRef.INT }));
            break;
        default:
            throw new IllegalStateException("Unsupported number of dimensions : " + theDimensions.size());
    }
    print("(call $");
    print(theMethodName);
    // UNUSED argument
    print(" (i32.const 0) ");
    for (Value theDimension : theDimensions) {
        print(" ");
        writeValue(theDimension);
    }
    // We also need the runtime class
    print(" (get_global $jlrArray__runtimeClass)");
    // Plus the vtable index
    print(" (i32.const ");
    print(idResolver.resolveVTableMethodByType(BytecodeObjectTypeRef.fromRuntimeClass(Array.class)));
    print(")");
    println(") ;; new array of type " + theType);
}
Also used : BytecodeTypeRef(de.mirkosertic.bytecoder.core.BytecodeTypeRef) BytecodeMethodSignature(de.mirkosertic.bytecoder.core.BytecodeMethodSignature) Address(de.mirkosertic.bytecoder.classlib.Address) StringValue(de.mirkosertic.bytecoder.ssa.StringValue) ByteValue(de.mirkosertic.bytecoder.ssa.ByteValue) Value(de.mirkosertic.bytecoder.ssa.Value) ClassReferenceValue(de.mirkosertic.bytecoder.ssa.ClassReferenceValue) FloatValue(de.mirkosertic.bytecoder.ssa.FloatValue) NullValue(de.mirkosertic.bytecoder.ssa.NullValue) DoubleValue(de.mirkosertic.bytecoder.ssa.DoubleValue) IntegerValue(de.mirkosertic.bytecoder.ssa.IntegerValue) LongValue(de.mirkosertic.bytecoder.ssa.LongValue) ShortValue(de.mirkosertic.bytecoder.ssa.ShortValue)

Example 15 with BytecodeMethodSignature

use of de.mirkosertic.bytecoder.core.BytecodeMethodSignature in project Bytecoder by mirkosertic.

the class InvokeVirtualOptimizer method visit.

private Optional<DirectInvokeMethodExpression> visit(InvokeVirtualMethodExpression aExpression, BytecodeLinkerContext aLinkerContext) {
    String theMethodName = aExpression.getMethodName();
    BytecodeMethodSignature theSignature = aExpression.getSignature();
    BytecodeVirtualMethodIdentifier theIdentifier = aLinkerContext.getMethodCollection().toIdentifier(theMethodName, theSignature);
    List<BytecodeLinkedClass> theLinkedClasses = aLinkerContext.getClassesImplementingVirtualMethod(theIdentifier);
    if (theLinkedClasses.size() == 1) {
        // There is only one class implementing this method, so we can make a direct call
        BytecodeLinkedClass theLinked = theLinkedClasses.get(0);
        if (!theLinked.emulatedByRuntime()) {
            BytecodeMethod theMethod = theLinked.getBytecodeClass().methodByNameAndSignatureOrNull(theMethodName, theSignature);
            if (!theMethod.getAccessFlags().isAbstract()) {
                BytecodeObjectTypeRef theClazz = theLinked.getClassName();
                DirectInvokeMethodExpression theNewExpression = new DirectInvokeMethodExpression(theClazz, theMethodName, theSignature);
                aExpression.routeIncomingDataFlowsTo(theNewExpression);
                return Optional.of(theNewExpression);
            }
        }
    }
    return Optional.empty();
}
Also used : BytecodeVirtualMethodIdentifier(de.mirkosertic.bytecoder.core.BytecodeVirtualMethodIdentifier) BytecodeMethodSignature(de.mirkosertic.bytecoder.core.BytecodeMethodSignature) BytecodeObjectTypeRef(de.mirkosertic.bytecoder.core.BytecodeObjectTypeRef) BytecodeMethod(de.mirkosertic.bytecoder.core.BytecodeMethod) BytecodeLinkedClass(de.mirkosertic.bytecoder.core.BytecodeLinkedClass) DirectInvokeMethodExpression(de.mirkosertic.bytecoder.ssa.DirectInvokeMethodExpression)

Aggregations

BytecodeMethodSignature (de.mirkosertic.bytecoder.core.BytecodeMethodSignature)23 BytecodeTypeRef (de.mirkosertic.bytecoder.core.BytecodeTypeRef)10 BytecodeObjectTypeRef (de.mirkosertic.bytecoder.core.BytecodeObjectTypeRef)9 BytecodeLinkedClass (de.mirkosertic.bytecoder.core.BytecodeLinkedClass)7 BytecodeMethod (de.mirkosertic.bytecoder.core.BytecodeMethod)6 StringValue (de.mirkosertic.bytecoder.ssa.StringValue)6 PrintWriter (java.io.PrintWriter)6 CompileOptions (de.mirkosertic.bytecoder.backend.CompileOptions)5 BytecodeArrayTypeRef (de.mirkosertic.bytecoder.core.BytecodeArrayTypeRef)5 BytecodeLinkerContext (de.mirkosertic.bytecoder.core.BytecodeLinkerContext)5 DoubleValue (de.mirkosertic.bytecoder.ssa.DoubleValue)5 FloatValue (de.mirkosertic.bytecoder.ssa.FloatValue)5 IntegerValue (de.mirkosertic.bytecoder.ssa.IntegerValue)5 LongValue (de.mirkosertic.bytecoder.ssa.LongValue)5 BytecodeProgram (de.mirkosertic.bytecoder.core.BytecodeProgram)4 BytecodeResolvedMethods (de.mirkosertic.bytecoder.core.BytecodeResolvedMethods)4 ByteValue (de.mirkosertic.bytecoder.ssa.ByteValue)4 ClassReferenceValue (de.mirkosertic.bytecoder.ssa.ClassReferenceValue)4 Value (de.mirkosertic.bytecoder.ssa.Value)4 Test (org.junit.Test)4