JavaToGpu includes an ASM input path for advanced integrations that already generate bytecode.
Most application users should write normal Java source with @GPU. Use the ASM path only when you own the bytecode generation step and can keep the generated methods inside JavaToGpu's supported GPU subset.
Use this path when you have:
- A custom language or DSL that emits JVM bytecode.
- A compiler pipeline that already owns an AST or IR.
- A build step that can normalize code before JavaToGpu sees it.
- CI tooling that wants to preflight compiled classes or jars.
Do not use it as a general way to convert arbitrary Java libraries to GPU code.
Recommended:
your DSL/AST/IR -> supported JVM bytecode -> ASM preflight -> JavaToGpu compile -> OpenCL
Avoid:
arbitrary JVM bytecode -> automatic GPU recovery
The preflight step is important because it tells you what needs to be rewritten before compilation.
Generated bytecode should be simple and predictable:
- Static methods.
- Clear local variables for intermediate values.
- Simple loops and branches.
- Stable stack shape at branch merge points.
INVOKESTATICcalls to supported GPU helpers.- Primitive, vector, pointer, image, sampler, or struct-compatible signatures.
- Math and backend operations expressed through
GPU.*or known helper methods.
If your generator can choose between clever stack bytecode and boring local-variable bytecode, choose the boring version.
These are not part of the current alpha ASM input contract:
invokevirtual,invokeinterface, andinvokedynamicas general dispatch.- Exception tables and exception-driven control flow.
monitorenter,monitorexit, and Java synchronization semantics.- Runtime object allocation and object graph access.
- Recursion and dynamic call graphs.
- Unsupported field access, casts, type checks, and descriptors.
- JVM array metadata patterns that should be passed explicitly instead.
Use preflight before real lowering:
GpuProgramCompiler compiler = GpuProgramCompiler.createDefault();
AsmFrontendFailureReport report = compiler.reportStructuredAsmArtifact(pathToClassesOrJar);
if (!report.successful()) {
System.err.println(report.summaryLine());
report.failures().forEach(failure -> System.err.println(failure.summary()));
}The generic artifact preflight accepts:
- A
.classfile. - A directory containing
.classfiles. - A
.jarfile.
It scans in stable order and aggregates failures into one report.
For migration planning, use the readiness report:
AsmFrontendReadinessReport readiness = compiler
.reportStructuredAsmArtifactReadiness(pathToClassesOrJar);
System.err.println(readiness.summaryLine());Readiness verdicts:
supportedmeans the artifact matches the current supported subset.rewriteRequiredmeans an upstream generator can usually normalize the code.rejectedmeans the code likely needs manual redesign or new compiler support.
Migration buckets help group work into areas such as array metadata, object model, field state, static dispatch, synchronization, exceptions, or type signatures.
Use bytecode shape inventory when you want to understand arbitrary compiled artifacts before deciding what to support:
AsmBytecodeShapeInventoryReport inventory = compiler
.inventoryStructuredAsmArtifact(pathToClassesOrJar);
System.err.println(inventory.summaryLine());Inventory is read-only. It is useful for planning a broader ASM parser because it counts risky JVM shapes without changing what JavaToGpu accepts today.
Write a preflight report when CI should archive unsupported bytecode details:
compiler.writeStructuredAsmArtifactReport(
pathToClassesOrJar,
Path.of("build/reports/javatogpu-asm-preflight.properties")
);Fail the build after writing the report:
compiler.writeAndRequireStructuredAsmArtifactReport(
pathToClassesOrJar,
Path.of("build/reports/javatogpu-asm-preflight.properties")
);Use the combined snapshot when you want preflight failures, readiness, and shape inventory in one artifact:
compiler.writeAndRequireStructuredAsmArtifactSnapshot(
pathToClassesOrJar,
Path.of("build/reports/javatogpu-asm-artifact-snapshot.properties")
);Create a small Java entry point in your build tooling:
package buildsupport;
import net.sixik.ga_utils.javatogpu.frontend.GpuProgramCompiler;
import java.nio.file.Path;
public final class AsmPreflightMain {
private AsmPreflightMain() {
}
public static void main(String[] args) throws Exception {
if (args.length != 2) {
throw new IllegalArgumentException("Usage: AsmPreflightMain <classes-or-jar> <report.properties>");
}
GpuProgramCompiler.createDefault().writeAndRequireStructuredAsmArtifactReport(
Path.of(args[0]),
Path.of(args[1])
);
}
}Then wire it into Gradle:
tasks.register('javatogpuAsmPreflight', JavaExec) {
dependsOn classes
classpath = sourceSets.test.runtimeClasspath
mainClass = 'buildsupport.AsmPreflightMain'
args layout.buildDirectory.dir('classes/java/main').get().asFile.absolutePath,
layout.buildDirectory.file('reports/javatogpu-asm-preflight.properties').get().asFile.absolutePath
}
check.dependsOn tasks.named('javatogpuAsmPreflight')For packaged artifacts, make the task depend on jar and pass the jar path instead of the classes directory.
- Keep bytecode boring and explicit.
- Prefer static helper calls.
- Pass lengths, dimensions, and flags explicitly instead of reading JVM metadata.
- Flatten object state into parameters, structs, or packed buffers.
- Run preflight in CI before attempting real compilation.
- Treat ASM diagnostics as feedback for your generator, not as runtime failures.
A broader arbitrary-ASM parser is planned, but the current alpha contract stays conservative so integrations can generate predictable GPU-safe input.