MetaIR is a graph-based intermediate representation (IR) for JVM bytecode, built on Cliff Click's Sea-of-Nodes concept. The framework leverages the Java Class-File API introduced in Java 24 (JEP 484).
Most parts of the IR are taken from Bytecoder - Framework to interpret and transpile JVM bytecode to JavaScript, OpenCL or WebAssembly. , but were rewritten to be more flexible and extensible.
- Analysis: Transform and inspect existing JVM bytecode
- Visualization: Debug functionality for graph representation
- Optimization: Built-in peephole optimizations for graph reduction
- Integration: Built-in integration with JUnit Platform
- Cross-Compilation: Foundation framework for cross-compiler development. Hello OpenCL and WebAssembly!
- MetaIR covers all aspects of JVM bytecode, including:
- Control Flow: Branching, loops, exception handling
- Data Flow: Local variables, stack, memory
- Memory aliasing: Memory allocation, memory access
Please take a look at the Mandelbrot OpenCL example to see it in action. More tutorials will follow.
| Document | What you will find |
|---|---|
| IR Architecture | How MetaIR represents JVM bytecode as a graph — node types, edge semantics, the six-step parsing pipeline, PHI nodes, and exception handling. Start here if you want to understand or extend the IR. |
| Sequencer & Code Generation | How the graph is re-linearised into structured output code — dominator-guided sequencing, the block stack, break/continue resolution, and the backend interface for new targets. |
| API Reference | Programmatic entry point — ResolverContext, ResolvedClass, ResolvedMethod, ResolvedField, IRType, graph traversal, and DOTExporter. Start here to use MetaIR from your own code. |
| Testing Infrastructure | The @MetaIRTest JUnit Platform integration — how tests are discovered and executed, the six output artifacts written per method, and how to write assertion-based JUnit 5 tests. |
| Visualization | The four DOT graph types, visual conventions (node shapes, edge colors), how to render them with Graphviz, and the online test-suite browser. |
| Graph Optimization | Graph invariants, safe edge-mutation patterns, how to write analysis and optimization passes, worked constant-folding and dead-code-elimination examples. |
| OpenCL Example | End-to-end walkthrough of the Mandelbrot kernel compiled to OpenCL C via MetaIR. |
| Not yet implemented | Known gaps and unsupported bytecode features. |
| TODO | Planned work and open design questions. |
- Built on Java Class-File API (JEP 484)
- Implements Sea-of-Nodes IR design
- Further examples and documentation: SeaOfNodes/Simple
- 🚧 Scheduling logic for machine code transformation is under development.
- An excellent tutorial about the Class-File API: Build A Compiler With The Java Class-File API by Dr. James Hamilton
- IR Sequencing: Beyond Relooper: recursive translation of unstructured control flow to structured control flow (functional pearl)
- Compilers - Nuts and bolts of Programming Languages: Compilers - Nuts and bolts of Programming Languages
A simple Java example with constructor invocation, demonstrating the use of the JUnit Platform integration:
import de.mirkosertic.metair.ir.test.MetaIRTest;
@MetaIRTest
public class NewInstanceTest {
public void newInstance() {
new NewInstanceTest();
}
}
Class-File API Debug YAML:
- method name: newInstance
flags: [PUBLIC]
method type: ()V
attributes: [Code]
code:
max stack: 2
max locals: 1
attributes: [LineNumberTable, LocalVariableTable]
line numbers:
- {start: 0, line number: 12}
- {start: 8, line number: 13}
local variables:
- {start: 0, end: 9, slot: 0, name: this, type: Lde/mirkosertic/metair/ir/examples/NewInstanceTest;}
//stack map frame @0: {locals: [de/mirkosertic/metair/ir/examples/NewInstanceTest], stack: []}
0: {opcode: NEW, type: de/mirkosertic/metair/ir/examples/NewInstanceTest}
3: {opcode: DUP}
4: {opcode: INVOKESPECIAL, owner: de/mirkosertic/metair/ir/examples/NewInstanceTest, method name: <init>, method type: ()V}
7: {opcode: POP}
8: {opcode: RETURN}
Generated IR (raw and unoptimized):
A full set of examples can be found in the MetaIR Test Suite. Each directory corresponds to a single testcase, and you will find the Class-File API Debug YAML and the generated IR (raw and unoptimized) as well in dot(graphviz) notation and as SVG images.