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());
}
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;
}
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());
}
}
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);
}
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();
}
Aggregations