Search in sources :

Example 1 with BytecodeMethod

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

the class NaiveProgramGeneratorTest method newProgramFrom.

private Program newProgramFrom(BytecodeProgram aProgram, BytecodeMethodSignature aSignature) {
    BytecodeLinkerContext theContext = mock(BytecodeLinkerContext.class);
    ProgramGenerator theGenerator = NaiveProgramGenerator.FACTORY.createFor(theContext);
    BytecodeClass theClass = mock(BytecodeClass.class);
    BytecodeMethod theMethod = mock(BytecodeMethod.class);
    when(theMethod.getAccessFlags()).thenReturn(new BytecodeAccessFlags(0));
    when(theMethod.getSignature()).thenReturn(aSignature);
    BytecodeCodeAttributeInfo theCodeAttribute = mock(BytecodeCodeAttributeInfo.class);
    when(theCodeAttribute.getProgramm()).thenReturn(aProgram);
    when(theMethod.getCode(any())).thenReturn(theCodeAttribute);
    return theGenerator.generateFrom(theClass, theMethod);
}
Also used : BytecodeAccessFlags(de.mirkosertic.bytecoder.core.BytecodeAccessFlags) BytecodeLinkerContext(de.mirkosertic.bytecoder.core.BytecodeLinkerContext) BytecodeMethod(de.mirkosertic.bytecoder.core.BytecodeMethod) BytecodeCodeAttributeInfo(de.mirkosertic.bytecoder.core.BytecodeCodeAttributeInfo) BytecodeClass(de.mirkosertic.bytecoder.core.BytecodeClass)

Example 2 with BytecodeMethod

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

the class JSSSACompilerBackend method generateCodeFor.

@Override
public JSCompileResult generateCodeFor(CompileOptions aOptions, BytecodeLinkerContext aLinkerContext, Class aEntryPointClass, String aEntryPointMethodName, BytecodeMethodSignature aEntryPointSignatue) {
    BytecodeLinkedClass theExceptionRethrower = aLinkerContext.resolveClass(BytecodeObjectTypeRef.fromRuntimeClass(ExceptionRethrower.class));
    theExceptionRethrower.resolveStaticMethod("registerExceptionOutcome", registerExceptionOutcomeSignature);
    theExceptionRethrower.resolveStaticMethod("getLastOutcomeOrNullAndReset", getLastExceptionOutcomeSignature);
    StringWriter theStrWriter = new StringWriter();
    PrintWriter theWriter = new PrintWriter(theStrWriter);
    theWriter.println("'use strict';");
    theWriter.println();
    theWriter.println("var bytecoderGlobalMemory = [];");
    theWriter.println();
    theWriter.println("var bytecoder = {");
    theWriter.println();
    theWriter.println("     logDebug : function(aValue) { ");
    theWriter.println("         console.log(aValue);");
    theWriter.println("     }, ");
    theWriter.println();
    theWriter.println("     logByteArrayAsString : function(aArray) { ");
    theWriter.println("         var theResult = '';");
    theWriter.println("         for (var i=0;i<aArray.data.length;i++) {");
    theWriter.println("             theResult += String.fromCharCode(aArray.data[i]);");
    theWriter.println("         }");
    theWriter.println("         console.log(theResult);");
    theWriter.println("     }, ");
    theWriter.println();
    theWriter.println("     newString : function(aByteArray) { ");
    BytecodeObjectTypeRef theStringTypeRef = BytecodeObjectTypeRef.fromRuntimeClass(String.class);
    BytecodeObjectTypeRef theArrayTypeRef = BytecodeObjectTypeRef.fromRuntimeClass(Array.class);
    BytecodeMethodSignature theStringConstructorSignature = new BytecodeMethodSignature(BytecodePrimitiveTypeRef.VOID, new BytecodeTypeRef[] { new BytecodeArrayTypeRef(BytecodePrimitiveTypeRef.BYTE, 1) });
    // Construct a String
    theWriter.println("          var theNewString = new " + JSWriterUtils.toClassName(theStringTypeRef) + ".Create();");
    theWriter.println("          var theBytes = new " + JSWriterUtils.toClassName(theArrayTypeRef) + ".Create();");
    theWriter.println("          theBytes.data = aByteArray;");
    theWriter.println("          " + JSWriterUtils.toClassName(theStringTypeRef) + '.' + JSWriterUtils.toMethodName("init", theStringConstructorSignature) + "(theNewString, theBytes);");
    theWriter.println("          return theNewString;");
    theWriter.println("     },");
    theWriter.println();
    theWriter.println("     newMultiArray : function(aDimensions, aDefault) {");
    theWriter.println("         var theLength = aDimensions[0];");
    theWriter.println("         var theArray = bytecoder.newArray(theLength, aDefault);");
    theWriter.println("         if (aDimensions.length > 1) {");
    theWriter.println("             var theNewDimensions = aDimensions.slice(0);");
    theWriter.println("             theNewDimensions.shift();");
    theWriter.println("             for (var i=0;i<theLength;i++) {");
    theWriter.println("                 theArray.data[i] = bytecoder.newMultiArray(theNewDimensions, aDefault);");
    theWriter.println("             }");
    theWriter.println("         }");
    theWriter.println("         return theArray;");
    theWriter.println("     },");
    theWriter.println();
    theWriter.println("     newArray : function(aLength, aDefault) {");
    BytecodeObjectTypeRef theArrayType = BytecodeObjectTypeRef.fromRuntimeClass(Array.class);
    theWriter.println("          var theInstance = new " + JSWriterUtils.toClassName(theArrayType) + ".Create();");
    theWriter.println("          theInstance.data = [];");
    theWriter.println("          theInstance.data.length = aLength;");
    theWriter.println("          for (var i=0;i<aLength;i++) {");
    theWriter.println("             theInstance.data[i] = aDefault;");
    theWriter.println("          }");
    theWriter.println("          return theInstance;");
    theWriter.println("     },");
    theWriter.println();
    theWriter.println("     dynamicType : function(aFunction) { ");
    theWriter.println("         return new Proxy({}, {");
    theWriter.println("             get: function(target, name) {");
    theWriter.println("                 return function(inst, _p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9) {");
    theWriter.println("                    return aFunction(_p1, _p2, _p3, _p4, _p5, _p6, _p7, _p8, _p9);");
    theWriter.println("                 }");
    theWriter.println("             }");
    theWriter.println("         });");
    theWriter.println("     }, ");
    theWriter.println();
    theWriter.println("     resolveStaticCallSiteObject: function(aWhere, aKey, aProducerFunction) {");
    theWriter.println("         var resolvedCallsiteObject = aWhere.__staticCallSites[aKey];");
    theWriter.println("         if (resolvedCallsiteObject == null) {");
    theWriter.println("             resolvedCallsiteObject = aProducerFunction();");
    theWriter.println("             aWhere.__staticCallSites[aKey] = resolvedCallsiteObject;");
    theWriter.println("         }");
    theWriter.println("         return resolvedCallsiteObject;");
    theWriter.println("     },");
    theWriter.println();
    theWriter.println("     imports : [],");
    theWriter.println();
    theWriter.println("     stringpool : [],");
    theWriter.println();
    theWriter.println("};");
    theWriter.println();
    ConstantPool thePool = new ConstantPool();
    aLinkerContext.linkedClasses().forEach(theEntry -> {
        BytecodeLinkedClass theLinkedClass = theEntry.targetNode();
        // Here we collect everything that is required for class initialization
        // this includes the super class, all implementing interfaces and also static
        // dependencies of the class initialization code
        List<BytecodeObjectTypeRef> theInitDependencies = new ArrayList<>();
        BytecodeLinkedClass theSuperClass = theLinkedClass.getSuperClass();
        if (theSuperClass != null) {
            theInitDependencies.add(theSuperClass.getClassName());
        }
        for (BytecodeLinkedClass theInterface : theLinkedClass.getImplementingTypes()) {
            if (!theInitDependencies.contains(theInterface.getClassName())) {
                theInitDependencies.add(theInterface.getClassName());
            }
        }
        BytecodeResolvedMethods theMethods = theLinkedClass.resolvedMethods();
        String theJSClassName = JSWriterUtils.toClassName(theEntry.edgeType().objectTypeRef());
        theWriter.println("var " + theJSClassName + " = {");
        // First of all, we add static fields required by the framework
        theWriter.println("    __initialized : false,");
        theWriter.println("    __staticCallSites : [],");
        theWriter.print("    __typeId : ");
        theWriter.print(theLinkedClass.getUniqueId());
        theWriter.println(",");
        theWriter.print("    __implementedTypes : [");
        {
            boolean first = true;
            for (BytecodeLinkedClass theType : theLinkedClass.getImplementingTypes()) {
                if (!first) {
                    theWriter.print(",");
                }
                first = false;
                theWriter.print(theType.getUniqueId());
            }
        }
        theWriter.println("],");
        // then we add class specific static fields
        BytecodeResolvedFields theStaticFields = theLinkedClass.resolvedFields();
        theStaticFields.streamForStaticFields().forEach(aFieldEntry -> {
            BytecodeTypeRef theFieldType = aFieldEntry.getValue().getTypeRef();
            if (theFieldType.isPrimitive()) {
                BytecodePrimitiveTypeRef thePrimitive = (BytecodePrimitiveTypeRef) theFieldType;
                switch(thePrimitive) {
                    case BOOLEAN:
                        {
                            theWriter.print("    ");
                            theWriter.print(aFieldEntry.getValue().getName().stringValue());
                            theWriter.print(" : false, // declared in ");
                            theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
                            break;
                        }
                    default:
                        {
                            theWriter.print("    ");
                            theWriter.print(aFieldEntry.getValue().getName().stringValue());
                            theWriter.print(" : 0, // declared in ");
                            theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
                            break;
                        }
                }
            } else {
                theWriter.print("    ");
                theWriter.print(aFieldEntry.getValue().getName().stringValue());
                theWriter.print(" : null, // declared in ");
                theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
            }
        });
        theWriter.println();
        if (!theLinkedClass.getBytecodeClass().getAccessFlags().isAbstract()) {
            // The Constructor function initializes all object members with null
            // Only non abstract classes can be instantiated
            BytecodeResolvedFields theInstanceFields = theLinkedClass.resolvedFields();
            theWriter.println("    Create : function() {");
            theInstanceFields.streamForInstanceFields().forEach(aFieldEntry -> {
                BytecodeTypeRef theFieldType = aFieldEntry.getValue().getTypeRef();
                if (theFieldType.isPrimitive()) {
                    BytecodePrimitiveTypeRef thePrimitive = (BytecodePrimitiveTypeRef) theFieldType;
                    switch(thePrimitive) {
                        case BOOLEAN:
                            {
                                theWriter.print("        this.");
                                theWriter.print(aFieldEntry.getValue().getName().stringValue());
                                theWriter.print(" = false; // declared in ");
                                theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
                                break;
                            }
                        default:
                            {
                                theWriter.print("        this.");
                                theWriter.print(aFieldEntry.getValue().getName().stringValue());
                                theWriter.print(" = 0; // declared in ");
                                theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
                                break;
                            }
                    }
                } else {
                    theWriter.print("        this.");
                    theWriter.print(aFieldEntry.getValue().getName().stringValue());
                    theWriter.print(" = null; // declared in ");
                    theWriter.println(aFieldEntry.getProvidingClass().getClassName().name());
                }
            });
            theWriter.println("    },");
            theWriter.println();
        }
        if (!theLinkedClass.getBytecodeClass().getAccessFlags().isInterface()) {
            theWriter.println("    instanceOf : function(aType) {");
            theWriter.print("        return ");
            theWriter.print(theJSClassName);
            theWriter.println(".__implementedTypes.includes(aType.__typeId);");
            theWriter.println("    },");
            theWriter.println();
            theWriter.println("    ClassgetClass : function() {");
            theWriter.print("        return ");
            theWriter.print(theJSClassName);
            theWriter.println(";");
            theWriter.println("    },");
            theWriter.println();
            theWriter.println("    BOOLEANdesiredAssertionStatus : function() {");
            theWriter.println("        return false;");
            theWriter.println("    },");
            theWriter.println();
            theWriter.println("    A1jlObjectgetEnumConstants : function(aClazz) {");
            theWriter.println("        return aClazz.$VALUES;");
            theWriter.println("    },");
        }
        theMethods.stream().forEach(aEntry -> {
            BytecodeMethod theMethod = aEntry.getValue();
            BytecodeMethodSignature theCurrentMethodSignature = theMethod.getSignature();
            // If the method is provided by the runtime, we do not need to generate the implementation
            if (theMethod.getAttributes().getAnnotationByType(EmulatedByRuntime.class.getName()) != null) {
                return;
            }
            // Do not generate code for abstract methods
            if (theMethod.getAccessFlags().isAbstract()) {
                return;
            }
            if (!(aEntry.getProvidingClass() == theLinkedClass)) {
                // But include static methods, as they are inherited from the base classes
                if (aEntry.getValue().getAccessFlags().isStatic() && !aEntry.getValue().isClassInitializer()) {
                    StringBuilder theArguments = new StringBuilder();
                    ;
                    for (int i = 0; i < theCurrentMethodSignature.getArguments().length; i++) {
                        if (i > 0) {
                            theArguments.append(',');
                        }
                        theArguments.append('p');
                        theArguments.append(i);
                    }
                    // Static methods will just delegate to the implementation in the class
                    theWriter.println();
                    theWriter.println("    " + JSWriterUtils.toMethodName(theMethod.getName().stringValue(), theCurrentMethodSignature) + " : function(" + theArguments + ") {");
                    if (!theCurrentMethodSignature.getReturnType().isVoid()) {
                        theWriter.print("         return ");
                    } else {
                        theWriter.print("         ");
                    }
                    theWriter.print(JSWriterUtils.toClassName(aEntry.getProvidingClass().getClassName()));
                    theWriter.print(".");
                    theWriter.print(JSWriterUtils.toMethodName(theMethod.getName().stringValue(), theCurrentMethodSignature));
                    theWriter.print("(");
                    theWriter.print(theArguments);
                    theWriter.println(");");
                    theWriter.println("    },");
                }
                return;
            }
            aLinkerContext.getLogger().info("Compiling {}.{}", theLinkedClass.getClassName().name(), theMethod.getName().stringValue());
            ProgramGenerator theGenerator = programGeneratorFactory.createFor(aLinkerContext);
            Program theSSAProgram = theGenerator.generateFrom(aEntry.getProvidingClass().getBytecodeClass(), theMethod);
            // Run optimizer
            aOptions.getOptimizer().optimize(theSSAProgram.getControlFlowGraph(), aLinkerContext);
            StringBuilder theArguments = new StringBuilder();
            for (Program.Argument theArgument : theSSAProgram.getArguments()) {
                if (theArguments.length() > 0) {
                    theArguments.append(',');
                }
                theArguments.append(theArgument.getVariable().getName());
            }
            if (theMethod.getAccessFlags().isNative()) {
                if (theLinkedClass.getBytecodeClass().getAttributes().getAnnotationByType(EmulatedByRuntime.class.getName()) != null) {
                    return;
                }
                BytecodeImportedLink theLink = theLinkedClass.linkfor(theMethod);
                theWriter.println();
                theWriter.println("    " + JSWriterUtils.toMethodName(theMethod.getName().stringValue(), theCurrentMethodSignature) + " : function(" + theArguments + ") {");
                theWriter.print("         return bytecoder.imports.");
                theWriter.print(theLink.getModuleName());
                theWriter.print(".");
                theWriter.print(theLink.getLinkName());
                theWriter.print("(");
                theWriter.print(theArguments);
                theWriter.println(");");
                theWriter.println("    },");
                return;
            }
            theWriter.println();
            theWriter.println("    " + JSWriterUtils.toMethodName(theMethod.getName().stringValue(), theCurrentMethodSignature) + " : function(" + theArguments + ") {");
            if (Objects.equals(theMethod.getName().stringValue(), "<clinit>")) {
                for (BytecodeObjectTypeRef theRef : theSSAProgram.getStaticReferences()) {
                    if (!theInitDependencies.contains(theRef)) {
                        theInitDependencies.add(theRef);
                    }
                }
            }
            if (aOptions.isDebugOutput()) {
                theWriter.println("        /**");
                theWriter.println("        " + theSSAProgram.getControlFlowGraph().toDOT());
                theWriter.println("        */");
            }
            JSSSAWriter theVariablesWriter = new JSSSAWriter(aOptions, theSSAProgram, "        ", theWriter, aLinkerContext, thePool);
            for (Variable theVariable : theSSAProgram.globalVariables()) {
                if (!theVariable.isSynthetic()) {
                    theVariablesWriter.print("var ");
                    theVariablesWriter.print(theVariable.getName());
                    theVariablesWriter.print(" = null;");
                    theVariablesWriter.print(" // type is ");
                    theVariablesWriter.print(theVariable.resolveType().resolve().name());
                    theVariablesWriter.print(" # of inits = " + theVariable.incomingDataFlows().size());
                    theVariablesWriter.println();
                }
            }
            // Try to reloop it!
            try {
                Relooper theRelooper = new Relooper();
                Relooper.Block theReloopedBlock = theRelooper.reloop(theSSAProgram.getControlFlowGraph());
                theVariablesWriter.printRelooped(theReloopedBlock);
            } catch (Exception e) {
                System.out.println(theSSAProgram.getControlFlowGraph().toDOT());
                throw new IllegalStateException("Error relooping cfg for " + theLinkedClass.getClassName().name() + '.' + theMethod.getName().stringValue(), e);
            }
            theWriter.println("    },");
        });
        theWriter.println();
        theWriter.println("    classInitCheck : function() {");
        theWriter.println("        if (!" + theJSClassName + ".__initialized) {");
        theWriter.println("            " + theJSClassName + ".__initialized = true;");
        if (!theLinkedClass.getBytecodeClass().getAccessFlags().isAbstract()) {
            // Now we have to setup the prototype
            // Only in case this class can be instantiated of course
            theWriter.println("            var thePrototype = " + theJSClassName + ".Create.prototype;");
            theWriter.println("            thePrototype.instanceOf = " + theJSClassName + ".instanceOf;");
            theWriter.println("            thePrototype.ClassgetClass = " + theJSClassName + ".ClassgetClass;");
            List<BytecodeResolvedMethods.MethodEntry> theEntries = theMethods.stream().collect(Collectors.toList());
            Set<String> theVisitedMethods = new HashSet<>();
            for (int i = theEntries.size() - 1; i >= 0; i--) {
                BytecodeResolvedMethods.MethodEntry aEntry = theEntries.get(i);
                BytecodeMethod theMethod = aEntry.getValue();
                String theMethodName = JSWriterUtils.toMethodName(theMethod.getName().stringValue(), theMethod.getSignature());
                if (!theMethod.getAccessFlags().isStatic() && !theMethod.getAccessFlags().isAbstract() && !theMethod.isConstructor() && !theMethod.isClassInitializer()) {
                    if (theVisitedMethods.add(theMethodName)) {
                        theWriter.print("            thePrototype.");
                        theWriter.print(theMethodName);
                        theWriter.print(" = ");
                        theWriter.print(JSWriterUtils.toClassName(aEntry.getProvidingClass().getClassName()));
                        theWriter.print(".");
                        theWriter.print(theMethodName);
                        theWriter.println(";");
                    }
                }
            }
        }
        for (BytecodeObjectTypeRef theRef : theInitDependencies) {
            if (!Objects.equals(theRef, theEntry.edgeType().objectTypeRef())) {
                theWriter.print("            ");
                theWriter.print(JSWriterUtils.toClassName(theRef));
                theWriter.println(".classInitCheck();");
            }
        }
        if (theLinkedClass.hasClassInitializer()) {
            theWriter.println("            " + theJSClassName + ".VOIDclinit();");
        }
        theWriter.println("        }");
        theWriter.println("    },");
        theWriter.println();
        theWriter.println("};");
        theWriter.println();
    });
    theWriter.println();
    theWriter.println("bytecoder.bootstrap = function() {");
    List<StringValue> theValues = thePool.stringValues();
    for (int i = 0; i < theValues.size(); i++) {
        StringValue theValue = theValues.get(i);
        theWriter.print("    bytecoder.stringpool[");
        theWriter.print(i);
        theWriter.print("] = bytecoder.newString(");
        theWriter.print(JSWriterUtils.toArray(theValue.getStringValue().getBytes()));
        theWriter.println(");");
    }
    aLinkerContext.linkedClasses().forEach(aEntry -> {
        if (!aEntry.targetNode().getBytecodeClass().getAccessFlags().isInterface()) {
            theWriter.print("    ");
            theWriter.print(JSWriterUtils.toClassName(aEntry.edgeType().objectTypeRef()));
            theWriter.println(".classInitCheck();");
        }
    });
    theWriter.println("}");
    theWriter.flush();
    return new JSCompileResult(theStrWriter.toString());
}
Also used : Variable(de.mirkosertic.bytecoder.ssa.Variable) BytecodeMethodSignature(de.mirkosertic.bytecoder.core.BytecodeMethodSignature) ArrayList(java.util.ArrayList) BytecodeMethod(de.mirkosertic.bytecoder.core.BytecodeMethod) ProgramGenerator(de.mirkosertic.bytecoder.ssa.ProgramGenerator) BytecodeResolvedMethods(de.mirkosertic.bytecoder.core.BytecodeResolvedMethods) StringWriter(java.io.StringWriter) BytecodeLinkedClass(de.mirkosertic.bytecoder.core.BytecodeLinkedClass) StringValue(de.mirkosertic.bytecoder.ssa.StringValue) BytecodeResolvedFields(de.mirkosertic.bytecoder.core.BytecodeResolvedFields) PrintWriter(java.io.PrintWriter) HashSet(java.util.HashSet) BytecodeProgram(de.mirkosertic.bytecoder.core.BytecodeProgram) Program(de.mirkosertic.bytecoder.ssa.Program) BytecodePrimitiveTypeRef(de.mirkosertic.bytecoder.core.BytecodePrimitiveTypeRef) BytecodeTypeRef(de.mirkosertic.bytecoder.core.BytecodeTypeRef) BytecodeObjectTypeRef(de.mirkosertic.bytecoder.core.BytecodeObjectTypeRef) Relooper(de.mirkosertic.bytecoder.relooper.Relooper) BytecodeArrayTypeRef(de.mirkosertic.bytecoder.core.BytecodeArrayTypeRef) ConstantPool(de.mirkosertic.bytecoder.backend.ConstantPool) BytecodeImportedLink(de.mirkosertic.bytecoder.core.BytecodeImportedLink) ExceptionRethrower(de.mirkosertic.bytecoder.classlib.ExceptionRethrower)

Example 3 with BytecodeMethod

use of de.mirkosertic.bytecoder.core.BytecodeMethod 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 4 with BytecodeMethod

use of de.mirkosertic.bytecoder.core.BytecodeMethod 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 5 with BytecodeMethod

use of de.mirkosertic.bytecoder.core.BytecodeMethod 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

BytecodeMethod (de.mirkosertic.bytecoder.core.BytecodeMethod)8 BytecodeLinkedClass (de.mirkosertic.bytecoder.core.BytecodeLinkedClass)7 BytecodeMethodSignature (de.mirkosertic.bytecoder.core.BytecodeMethodSignature)7 BytecodeObjectTypeRef (de.mirkosertic.bytecoder.core.BytecodeObjectTypeRef)5 BytecodeTypeRef (de.mirkosertic.bytecoder.core.BytecodeTypeRef)5 BytecodeArrayTypeRef (de.mirkosertic.bytecoder.core.BytecodeArrayTypeRef)4 BytecodeLinkerContext (de.mirkosertic.bytecoder.core.BytecodeLinkerContext)4 BytecodeClass (de.mirkosertic.bytecoder.core.BytecodeClass)3 BytecodeResolvedMethods (de.mirkosertic.bytecoder.core.BytecodeResolvedMethods)3 ArrayList (java.util.ArrayList)3 HashSet (java.util.HashSet)3 ConstantPool (de.mirkosertic.bytecoder.backend.ConstantPool)2 Address (de.mirkosertic.bytecoder.classlib.Address)2 MemoryManager (de.mirkosertic.bytecoder.classlib.MemoryManager)2 BytecodeAnnotation (de.mirkosertic.bytecoder.core.BytecodeAnnotation)2 BytecodeCodeAttributeInfo (de.mirkosertic.bytecoder.core.BytecodeCodeAttributeInfo)2 BytecodeImportedLink (de.mirkosertic.bytecoder.core.BytecodeImportedLink)2 Relooper (de.mirkosertic.bytecoder.relooper.Relooper)2 Program (de.mirkosertic.bytecoder.ssa.Program)2 ProgramGenerator (de.mirkosertic.bytecoder.ssa.ProgramGenerator)2