git » larquil.git » commit 57eca72

Port classfile backend to Larquil

author Alan
2026-05-01 21:30:04 UTC
committer Alan
2026-05-01 21:30:04 UTC
parent 425ad6d283bc958dd940fdc702555c001cf00e72

Port classfile backend to Larquil

Makefile +3 -3
bootstrap/stage1-compiler.jar +0 -0
specs/stage1.md +28 -37
src/com/tailrecursion/larquil/stage0/BranchPatch.java +0 -13
src/com/tailrecursion/larquil/stage0/ByteVec.java +0 -47
src/com/tailrecursion/larquil/stage0/ClassFile.java +0 -190
src/com/tailrecursion/larquil/stage0/CpEntry.java +0 -11
src/com/tailrecursion/larquil/stage0/FieldInfo.java +0 -13
src/com/tailrecursion/larquil/stage0/MethodCode.java +0 -199
src/com/tailrecursion/larquil/stage0/Pair.java +0 -11
src/com/tailrecursion/larquil/stage0/Writer.java +0 -31
stage1/backend.lql +51 -66
stage1/classfile.lql +1643 -0
stage1/compiler.lql +6 -4
stage1/emit.lql +190 -119
stage1/instructions.lql +7 -10
test/run.sh +1 -5

diff --git a/Makefile b/Makefile
index 14c3fa8..ccec321 100644
--- a/Makefile
+++ b/Makefile
@@ -23,10 +23,10 @@ test: build
 stage1-build: build
 	rm -rf $(STAGE1_DIR)
 	mkdir -p $(STAGE1_DIR)
-	for f in stage1/core.lql stage1/munge.lql stage1/emit.lql; do \
+	for f in stage1/core.lql stage1/munge.lql; do \
 		$(JAVA) -cp $(BOOTSTRAP_DIR)/stage1-compiler.jar:$(CLASSES_DIR) com.tailrecursion.larquil.stage0.Stage1Main $$f $(STAGE1_DIR); \
 	done
-	cat stage1/core.lql stage1/munge.lql stage1/forms.lql stage1/reader.lql stage1/emit.lql stage1/instructions.lql stage1/backend.lql stage1/compiler.lql > $(STAGE1_DIR)/compiler.lql
+	cat stage1/core.lql stage1/munge.lql stage1/forms.lql stage1/reader.lql stage1/classfile.lql stage1/emit.lql stage1/instructions.lql stage1/backend.lql stage1/compiler.lql > $(STAGE1_DIR)/compiler.lql
 	$(JAVA) -cp $(BOOTSTRAP_DIR)/stage1-compiler.jar:$(CLASSES_DIR) com.tailrecursion.larquil.stage0.Stage1Main $(STAGE1_DIR)/compiler.lql $(STAGE1_DIR)
 
 stage1-test: stage1-build
@@ -48,7 +48,7 @@ bootstrap-artifact: stage1-self-host
 bootstrap-test: build
 	rm -rf $(BOOTSTRAP_TEST_DIR)
 	mkdir -p $(BOOTSTRAP_TEST_DIR)
-	cat stage1/core.lql stage1/munge.lql stage1/forms.lql stage1/reader.lql stage1/emit.lql stage1/instructions.lql stage1/backend.lql stage1/compiler.lql > $(BOOTSTRAP_TEST_DIR)/compiler.lql
+	cat stage1/core.lql stage1/munge.lql stage1/forms.lql stage1/reader.lql stage1/classfile.lql stage1/emit.lql stage1/instructions.lql stage1/backend.lql stage1/compiler.lql > $(BOOTSTRAP_TEST_DIR)/compiler.lql
 	$(JAVA) -cp $(BOOTSTRAP_DIR)/stage1-compiler.jar:$(CLASSES_DIR) com.tailrecursion.larquil.stage0.Stage1Main $(BOOTSTRAP_TEST_DIR)/compiler.lql $(BOOTSTRAP_TEST_DIR)
 	sh test/run-stage1.sh $(BOOTSTRAP_TEST_DIR)
 
diff --git a/bootstrap/stage1-compiler.jar b/bootstrap/stage1-compiler.jar
index bc93815..c7f5c29 100644
Binary files a/bootstrap/stage1-compiler.jar and b/bootstrap/stage1-compiler.jar differ
diff --git a/specs/stage1.md b/specs/stage1.md
index 6465ca8..e9b1b66 100644
--- a/specs/stage1.md
+++ b/specs/stage1.md
@@ -100,29 +100,29 @@ Registry format:
 
 Current temporary support:
 
-- Name: `MethodCode`
-  Step: byte emission and instruction lowering
-  Reason: lets early Stage 1 functions emit into the existing classfile writer
-  Replacement: Larquil-owned method/code record plus Larquil byte vector
-  Removal condition: Stage 1 `bytevec.lql` and method writer emit loadable methods
-
-- Name: `ClassFile`
-  Step: class assembly and constant-pool work
-  Reason: lets Stage 1 build classes before the constant-pool writer is ported
-  Replacement: Larquil-owned classfile state and constant-pool helpers
-  Removal condition: Stage 1 classfile writer emits loader and helper classes directly
-
 - Name: `FunctionDef`
   Step: function form analysis
   Reason: keeps the first form-analysis port aligned with the Java compiler
   Replacement: Larquil-shaped list or simple record representation
   Removal condition: Stage 1 form analysis and instruction lowering agree on the Larquil representation
 
-- Name: `Pair`
-  Step: symbol tables and association lists
-  Reason: association-list entries need a simple representation during early porting
-  Replacement: Larquil list pair representation or dedicated Larquil pair value
-  Removal condition: `stage1/core.lql` owns lookup and pair construction
+- Name: `IFunction`
+  Step: runtime invocation ABI
+  Reason: generated function classes still implement the Java bootstrap interface
+  Replacement: Larquil-generated `IFunction.class`
+  Removal condition: the bootstrap artifact ships an equivalent generated interface
+
+- Name: `Symbol`
+  Step: reader/runtime symbol values
+  Reason: parsed symbols still use the Java runtime class
+  Replacement: Larquil-generated `Symbol.class`
+  Removal condition: generated `Symbol` preserves interning, `name`, equality, hash, and string conversion
+
+- Name: `Stage1Main`
+  Step: command-line launcher
+  Reason: Makefile/tests still need a small Java entry point to call the compiler
+  Replacement: Larquil-generated launcher class
+  Removal condition: build/test targets invoke the generated launcher without compiling Java sources
 
 - Name: CLI/file bridge
   Step: Stage 1 entrypoint
@@ -428,13 +428,7 @@ Functions to port:
 
 Temporary Java support allowed:
 
-- `ClassFile`
-- `MethodCode`
-- `FieldInfo`
-- `CpEntry`
-- `BranchPatch`
-- `Writer`
-- `ByteVec`
+- none for classfile writing or method bytecode assembly
 
 Done when:
 
@@ -443,12 +437,15 @@ Done when:
 
 ## 9. Port Constant Pool And Byte Vector
 
+Status: done in `stage1/classfile.lql`.
+
 Port the direct classfile writer internals.
 
 Source target:
 
 - `stage1/classfile.lql`
-- `stage1/bytevec.lql`
+- JDK `DataOutputStream` is used for classfile output
+- JDK `ByteBuffer` is used for mutable method bytecode and branch patching
 
 Functions/data to port:
 
@@ -642,20 +639,14 @@ Done when:
 
 ---
 
-# Current First Chunk
-
-The first chunk is `stage1/emit.lql`.
-It ports low-level byte emission wrappers first because they are small, stable, and close to JVM bytecode.
+# Current Chunk
 
-Current functions:
+The classfile backend is now Larquil-owned:
 
-- `emit_u1`
-- `emit_aconst_null`
-- `emit_areturn`
-- `emit_return_void`
-- `emit_pop`
+- `stage1/classfile.lql` owns class records, constant-pool helpers, method records, labels, branch patching, and classfile writing
+- `stage1/emit.lql` emits through those Larquil records
+- the refreshed bootstrap artifact has no references to the removed Java classfile backend
 
 Next best chunk:
 
-- expand `stage1/emit.lql` to cover the remaining `MethodCode` byte-emission helpers
-- add tests that call the generated helpers against a real `MethodCode` object
+- generate `IFunction.class` from Larquil classfile helpers and remove `IFunction.java`
diff --git a/src/com/tailrecursion/larquil/stage0/BranchPatch.java b/src/com/tailrecursion/larquil/stage0/BranchPatch.java
deleted file mode 100644
index b319ac4..0000000
--- a/src/com/tailrecursion/larquil/stage0/BranchPatch.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.tailrecursion.larquil.stage0;
-
-final class BranchPatch {
-    final String label;
-    final int opPos;
-    final int patchPos;
-
-    BranchPatch(String label, int opPos, int patchPos) {
-        this.label = label;
-        this.opPos = opPos;
-        this.patchPos = patchPos;
-    }
-}
diff --git a/src/com/tailrecursion/larquil/stage0/ByteVec.java b/src/com/tailrecursion/larquil/stage0/ByteVec.java
deleted file mode 100644
index 21027e1..0000000
--- a/src/com/tailrecursion/larquil/stage0/ByteVec.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.tailrecursion.larquil.stage0;
-
-final class ByteVec {
-    byte[] data = new byte[256];
-    int len = 0;
-
-    void add(int b) {
-        grow(1);
-        data[len] = (byte) (b & 0xff);
-        len = len + 1;
-    }
-
-    void u2(int v) {
-        add(v >> 8);
-        add(v);
-    }
-
-    void u4(int v) {
-        add(v >> 24);
-        add(v >> 16);
-        add(v >> 8);
-        add(v);
-    }
-
-    void patchS2(int pos, int v) {
-        if (v < -32768 || v > 32767) {
-            throw new RuntimeException("branch offset out of range: " + v);
-        }
-        data[pos] = (byte) ((v >> 8) & 0xff);
-        data[pos + 1] = (byte) (v & 0xff);
-    }
-
-    byte[] bytes() {
-        byte[] out = new byte[len];
-        System.arraycopy(data, 0, out, 0, len);
-        return out;
-    }
-
-    void grow(int n) {
-        if (len + n <= data.length) {
-            return;
-        }
-        byte[] next = new byte[data.length * 2 + n];
-        System.arraycopy(data, 0, next, 0, len);
-        data = next;
-    }
-}
diff --git a/src/com/tailrecursion/larquil/stage0/ClassFile.java b/src/com/tailrecursion/larquil/stage0/ClassFile.java
deleted file mode 100644
index 3a168b5..0000000
--- a/src/com/tailrecursion/larquil/stage0/ClassFile.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package com.tailrecursion.larquil.stage0;
-
-import java.io.ByteArrayOutputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-final class ClassFile {
-    final String name;
-    final ArrayList<Object> cp = new ArrayList<Object>();
-    final HashMap<String, Integer> cpIndex = new HashMap<String, Integer>();
-    final ArrayList<Object> fields = new ArrayList<Object>();
-    final ArrayList<Object> methods = new ArrayList<Object>();
-    final ArrayList<Object> interfaces = new ArrayList<Object>();
-
-    ClassFile(String name) {
-        this.name = name;
-        cpClass(name);
-        cpClass("java/lang/Object");
-    }
-
-    void addInterface(String iface) {
-        interfaces.add(Integer.valueOf(cpClass(iface)));
-    }
-
-    void addField(int access, String name, String desc) {
-        fields.add(new FieldInfo(access, cpUtf8(name), cpUtf8(desc)));
-    }
-
-    void addMethod(MethodCode m) {
-        methods.add(m);
-    }
-
-    int cpUtf8(String value) {
-        String key = "U:" + value;
-        Integer got = cpIndex.get(key);
-        if (got != null) {
-            return got.intValue();
-        }
-        int idx = cp.size() + 1;
-        cp.add(new CpEntry(1, value));
-        cpIndex.put(key, Integer.valueOf(idx));
-        return idx;
-    }
-
-    int cpClass(String cls) {
-        String key = "C:" + cls;
-        Integer got = cpIndex.get(key);
-        if (got != null) {
-            return got.intValue();
-        }
-        int nameIdx = cpUtf8(cls);
-        int idx = cp.size() + 1;
-        cp.add(new CpEntry(7, Integer.valueOf(nameIdx)));
-        cpIndex.put(key, Integer.valueOf(idx));
-        return idx;
-    }
-
-    int cpLong(long value) {
-        String key = "J:" + value;
-        Integer got = cpIndex.get(key);
-        if (got != null) {
-            return got.intValue();
-        }
-        int idx = cp.size() + 1;
-        cp.add(new CpEntry(5, Long.valueOf(value)));
-        cp.add(null);
-        cpIndex.put(key, Integer.valueOf(idx));
-        return idx;
-    }
-
-    int cpString(String value) {
-        String key = "S:" + value;
-        Integer got = cpIndex.get(key);
-        if (got != null) {
-            return got.intValue();
-        }
-        int utf8Index = cpUtf8(value);
-        int idx = cp.size() + 1;
-        cp.add(new CpEntry(8, Integer.valueOf(utf8Index)));
-        cpIndex.put(key, Integer.valueOf(idx));
-        return idx;
-    }
-
-    int cpNameType(String name, String desc) {
-        String key = "NT:" + name + ":" + desc;
-        Integer got = cpIndex.get(key);
-        if (got != null) {
-            return got.intValue();
-        }
-        int nameIndex = cpUtf8(name);
-        int descIndex = cpUtf8(desc);
-        int idx = cp.size() + 1;
-        cp.add(new CpEntry(12, new int[]{nameIndex, descIndex}));
-        cpIndex.put(key, Integer.valueOf(idx));
-        return idx;
-    }
-
-    int cpFieldref(String cls, String name, String desc) {
-        return cpRef(9, "F:", cls, name, desc);
-    }
-
-    int cpMethodref(String cls, String name, String desc) {
-        return cpRef(10, "M:", cls, name, desc);
-    }
-
-    int cpInterfaceMethodref(String cls, String name, String desc) {
-        return cpRef(11, "IM:", cls, name, desc);
-    }
-
-    int cpRef(int tag, String prefix, String cls, String name, String desc) {
-        String key = prefix + cls + ":" + name + ":" + desc;
-        Integer got = cpIndex.get(key);
-        if (got != null) {
-            return got.intValue();
-        }
-        int classIndex = cpClass(cls);
-        int nameTypeIndex = cpNameType(name, desc);
-        int idx = cp.size() + 1;
-        cp.add(new CpEntry(tag, new int[]{classIndex, nameTypeIndex}));
-        cpIndex.put(key, Integer.valueOf(idx));
-        return idx;
-    }
-
-    byte[] bytes() {
-        cpUtf8("Code");
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
-        Writer w = new Writer(out);
-        w.u4(0xcafebabe);
-        w.u2(0);
-        w.u2(49);
-        w.u2(cp.size() + 1);
-        int i = 0;
-        while (i < cp.size()) {
-            CpEntry e = (CpEntry) cp.get(i);
-            if (e != null) {
-                writeCp(w, e);
-            }
-            i = i + 1;
-        }
-        w.u2(0x0031);
-        w.u2(cpClass(name));
-        w.u2(cpClass("java/lang/Object"));
-        w.u2(interfaces.size());
-        i = 0;
-        while (i < interfaces.size()) {
-            w.u2(((Integer) interfaces.get(i)).intValue());
-            i = i + 1;
-        }
-        w.u2(fields.size());
-        i = 0;
-        while (i < fields.size()) {
-            FieldInfo f = (FieldInfo) fields.get(i);
-            w.u2(f.access);
-            w.u2(f.name);
-            w.u2(f.desc);
-            w.u2(0);
-            i = i + 1;
-        }
-        w.u2(methods.size());
-        i = 0;
-        while (i < methods.size()) {
-            ((MethodCode) methods.get(i)).write(w);
-            i = i + 1;
-        }
-        w.u2(0);
-        return out.toByteArray();
-    }
-
-    void writeCp(Writer w, CpEntry e) {
-        w.u1(e.tag);
-        if (e.tag == 1) {
-            byte[] bytes = ((String) e.value).getBytes(StandardCharsets.UTF_8);
-            w.u2(bytes.length);
-            w.bytes(bytes);
-        } else if (e.tag == 7 || e.tag == 8) {
-            w.u2(((Integer) e.value).intValue());
-        } else if (e.tag == 5) {
-            long v = ((Long) e.value).longValue();
-            w.u4((int) (v >> 32));
-            w.u4((int) v);
-        } else if (e.tag == 9 || e.tag == 10 || e.tag == 11 || e.tag == 12) {
-            int[] pair = (int[]) e.value;
-            w.u2(pair[0]);
-            w.u2(pair[1]);
-        } else {
-            throw new RuntimeException("bad cp tag: " + e.tag);
-        }
-    }
-}
diff --git a/src/com/tailrecursion/larquil/stage0/CpEntry.java b/src/com/tailrecursion/larquil/stage0/CpEntry.java
deleted file mode 100644
index 69a5c96..0000000
--- a/src/com/tailrecursion/larquil/stage0/CpEntry.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.tailrecursion.larquil.stage0;
-
-final class CpEntry {
-    final int tag;
-    final Object value;
-
-    CpEntry(int tag, Object value) {
-        this.tag = tag;
-        this.value = value;
-    }
-}
diff --git a/src/com/tailrecursion/larquil/stage0/FieldInfo.java b/src/com/tailrecursion/larquil/stage0/FieldInfo.java
deleted file mode 100644
index fb8e5ca..0000000
--- a/src/com/tailrecursion/larquil/stage0/FieldInfo.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.tailrecursion.larquil.stage0;
-
-final class FieldInfo {
-    final int access;
-    final int name;
-    final int desc;
-
-    FieldInfo(int access, int name, int desc) {
-        this.access = access;
-        this.name = name;
-        this.desc = desc;
-    }
-}
diff --git a/src/com/tailrecursion/larquil/stage0/MethodCode.java b/src/com/tailrecursion/larquil/stage0/MethodCode.java
deleted file mode 100644
index 3821138..0000000
--- a/src/com/tailrecursion/larquil/stage0/MethodCode.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package com.tailrecursion.larquil.stage0;
-
-import java.util.ArrayList;
-
-final class MethodCode {
-    final ClassFile cf;
-    final int access;
-    final int nameIndex;
-    final int descIndex;
-    final ByteVec code = new ByteVec();
-    final ArrayList<Object> labels = new ArrayList<Object>();
-    final ArrayList<Object> patches = new ArrayList<Object>();
-    int maxStack = 64;
-    int maxLocals = 2;
-    int internal = 0;
-
-    MethodCode(ClassFile cf, int access, String name, String desc) {
-        this.cf = cf;
-        this.access = access;
-        this.nameIndex = cf.cpUtf8(name);
-        this.descIndex = cf.cpUtf8(desc);
-    }
-
-    int nextInternal() {
-        int v = internal;
-        internal = internal + 1;
-        return v;
-    }
-
-    void u1(int v) {
-        code.add(v);
-    }
-
-    void u2(int v) {
-        code.u2(v);
-    }
-
-    void pushInt(int v) {
-        if (v >= -1 && v <= 5) {
-            u1(0x03 + v);
-        } else if (v >= -128 && v <= 127) {
-            u1(0x10);
-            u1(v);
-        } else {
-            u1(0x11);
-            u2(v);
-        }
-    }
-
-    void aload(int slot) {
-        if (slot >= 0 && slot <= 3) {
-            u1(0x2a + slot);
-        } else {
-            u1(0x19);
-            u1(slot);
-        }
-    }
-
-    void astore(int slot) {
-        if (slot >= 0 && slot <= 3) {
-            u1(0x4b + slot);
-        } else {
-            u1(0x3a);
-            u1(slot);
-        }
-    }
-
-    void lconst(long value) {
-        u1(0x14);
-        u2(cf.cpLong(value));
-        invokestatic("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
-    }
-
-    void sconst(String value) {
-        int idx = cf.cpString(value);
-        if (idx <= 255) {
-            u1(0x12);
-            u1(idx);
-        } else {
-            u1(0x13);
-            u2(idx);
-        }
-    }
-
-    void getstatic(String cls, String name, String desc) {
-        u1(0xb2);
-        u2(cf.cpFieldref(cls, name, desc));
-    }
-
-    void putstatic(String cls, String name, String desc) {
-        u1(0xb3);
-        u2(cf.cpFieldref(cls, name, desc));
-    }
-
-    void getfield(String cls, String name, String desc) {
-        u1(0xb4);
-        u2(cf.cpFieldref(cls, name, desc));
-    }
-
-    void putfield(String cls, String name, String desc) {
-        u1(0xb5);
-        u2(cf.cpFieldref(cls, name, desc));
-    }
-
-    void checkcast(String cls) {
-        u1(0xc0);
-        u2(cf.cpClass(cls));
-    }
-
-    void newobj(String cls) {
-        u1(0xbb);
-        u2(cf.cpClass(cls));
-    }
-
-    void anewarray(String cls) {
-        u1(0xbd);
-        u2(cf.cpClass(cls));
-    }
-
-    void invokespecial(String cls, String name, String desc) {
-        u1(0xb7);
-        u2(cf.cpMethodref(cls, name, desc));
-    }
-
-    void invokevirtual(String cls, String name, String desc) {
-        u1(0xb6);
-        u2(cf.cpMethodref(cls, name, desc));
-    }
-
-    void invokestatic(String cls, String name, String desc) {
-        u1(0xb8);
-        u2(cf.cpMethodref(cls, name, desc));
-    }
-
-    void invokeinterface(String cls, String name, String desc, int count) {
-        u1(0xb9);
-        u2(cf.cpInterfaceMethodref(cls, name, desc));
-        u1(count);
-        u1(0);
-    }
-
-    void branch(int opcode, String label) {
-        int opPos = code.len;
-        u1(opcode);
-        int patchPos = code.len;
-        u2(0);
-        patches.add(new BranchPatch(label, opPos, patchPos));
-    }
-
-    void label(String name) {
-        if (lookupLabel(name) != null) {
-            throw new RuntimeException("duplicate label: " + name);
-        }
-        labels.add(new Pair(Symbol.intern(name), Integer.valueOf(code.len)));
-    }
-
-    Integer lookupLabel(String name) {
-        Symbol s = Symbol.intern(name);
-        int i = labels.size() - 1;
-        while (i >= 0) {
-            Pair p = (Pair) labels.get(i);
-            if (s.equals(p.a)) {
-                return (Integer) p.b;
-            }
-            i = i - 1;
-        }
-        return null;
-    }
-
-    void finishLabels() {
-        int i = 0;
-        while (i < patches.size()) {
-            BranchPatch p = (BranchPatch) patches.get(i);
-            Integer target = lookupLabel(p.label);
-            if (target == null) {
-                throw new RuntimeException("unresolved label: " + p.label);
-            }
-            code.patchS2(p.patchPos, target.intValue() - p.opPos);
-            i = i + 1;
-        }
-    }
-
-    void write(Writer w) {
-        finishLabels();
-        byte[] bytes = code.bytes();
-        w.u2(access);
-        w.u2(nameIndex);
-        w.u2(descIndex);
-        w.u2(1);
-        w.u2(cf.cpUtf8("Code"));
-        w.u4(12 + bytes.length);
-        w.u2(maxStack);
-        w.u2(maxLocals);
-        w.u4(bytes.length);
-        w.bytes(bytes);
-        w.u2(0);
-        w.u2(0);
-    }
-}
diff --git a/src/com/tailrecursion/larquil/stage0/Pair.java b/src/com/tailrecursion/larquil/stage0/Pair.java
deleted file mode 100644
index f218763..0000000
--- a/src/com/tailrecursion/larquil/stage0/Pair.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.tailrecursion.larquil.stage0;
-
-final class Pair {
-    final Object a;
-    final Object b;
-
-    Pair(Object a, Object b) {
-        this.a = a;
-        this.b = b;
-    }
-}
diff --git a/src/com/tailrecursion/larquil/stage0/Writer.java b/src/com/tailrecursion/larquil/stage0/Writer.java
deleted file mode 100644
index 35d28b1..0000000
--- a/src/com/tailrecursion/larquil/stage0/Writer.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.tailrecursion.larquil.stage0;
-
-import java.io.ByteArrayOutputStream;
-
-final class Writer {
-    final ByteArrayOutputStream out;
-
-    Writer(ByteArrayOutputStream out) {
-        this.out = out;
-    }
-
-    void u1(int v) {
-        out.write(v & 0xff);
-    }
-
-    void u2(int v) {
-        u1(v >> 8);
-        u1(v);
-    }
-
-    void u4(int v) {
-        u1(v >> 24);
-        u1(v >> 16);
-        u1(v >> 8);
-        u1(v);
-    }
-
-    void bytes(byte[] bytes) {
-        out.write(bytes, 0, bytes.length);
-    }
-}
diff --git a/stage1/backend.lql b/stage1/backend.lql
index 0397bc7..f101722 100644
--- a/stage1/backend.lql
+++ b/stage1/backend.lql
@@ -109,7 +109,6 @@
   (checkcast "java/util/ArrayList")
   (iconst 0)
   (invokevirtual "java/util/ArrayList" "get" "(I)Ljava/lang/Object;")
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
   (return))
 
 (function state_env (state)
@@ -143,14 +142,13 @@
   (load value)
   (invokevirtual "java/util/ArrayList" "set" "(ILjava/lang/Object;)Ljava/lang/Object;")
   (pop)
+  (load-function method_set_max_locals)
   (load-function state_method)
   (load state)
   (invoke 1)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
   (load value)
-  (checkcast "java/lang/Long")
-  (invokevirtual "java/lang/Long" "intValue" "()I")
-  (putfield "com/tailrecursion/larquil/stage0/MethodCode" "maxLocals" "I")
+  (invoke 2)
+  (pop)
   (aconst-null)
   (return))
 
@@ -269,14 +267,12 @@
   (return))
 
 (function add_constructor (cf)
-  (new "com/tailrecursion/larquil/stage0/MethodCode")
-  (dup)
+  (load-function method_code)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
-  (iconst 1)
+  (lconst 1)
   (sconst "<init>")
   (sconst "()V")
-  (invokespecial "com/tailrecursion/larquil/stage0/MethodCode" "<init>" "(Lcom/tailrecursion/larquil/stage0/ClassFile;ILjava/lang/String;Ljava/lang/String;)V")
+  (invoke 4)
   (store m)
   (load-function emit_u1)
   (load m)
@@ -294,23 +290,20 @@
   (load m)
   (invoke 1)
   (pop)
+  (load-function class_add_method)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
-  (invokevirtual "com/tailrecursion/larquil/stage0/ClassFile" "addMethod" "(Lcom/tailrecursion/larquil/stage0/MethodCode;)V")
+  (invoke 2)
   (aconst-null)
   (return))
 
 (function add_clinit (cf name)
-  (new "com/tailrecursion/larquil/stage0/MethodCode")
-  (dup)
+  (load-function method_code)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
-  (iconst 8)
+  (lconst 8)
   (sconst "<clinit>")
   (sconst "()V")
-  (invokespecial "com/tailrecursion/larquil/stage0/MethodCode" "<init>" "(Lcom/tailrecursion/larquil/stage0/ClassFile;ILjava/lang/String;Ljava/lang/String;)V")
+  (invoke 4)
   (store m)
   (load-function emit_new)
   (load m)
@@ -350,23 +343,20 @@
   (load m)
   (invoke 1)
   (pop)
+  (load-function class_add_method)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
-  (invokevirtual "com/tailrecursion/larquil/stage0/ClassFile" "addMethod" "(Lcom/tailrecursion/larquil/stage0/MethodCode;)V")
+  (invoke 2)
   (aconst-null)
   (return))
 
 (function add_main (cf name)
-  (new "com/tailrecursion/larquil/stage0/MethodCode")
-  (dup)
+  (load-function method_code)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
-  (iconst 9)
+  (lconst 9)
   (sconst "main")
   (sconst "([Ljava/lang/String;)V")
-  (invokespecial "com/tailrecursion/larquil/stage0/MethodCode" "<init>" "(Lcom/tailrecursion/larquil/stage0/ClassFile;ILjava/lang/String;Ljava/lang/String;)V")
+  (invoke 4)
   (store m)
   (load-function emit_getstatic)
   (load m)
@@ -411,11 +401,10 @@
   (load m)
   (invoke 1)
   (pop)
+  (load-function class_add_method)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
-  (invokevirtual "com/tailrecursion/larquil/stage0/ClassFile" "addMethod" "(Lcom/tailrecursion/larquil/stage0/MethodCode;)V")
+  (invoke 2)
   (aconst-null)
   (return))
 
@@ -424,19 +413,18 @@
   (load def)
   (invoke 1)
   (store class_name)
-  (new "com/tailrecursion/larquil/stage0/ClassFile")
-  (dup)
+  (load-function class_file)
   (load class_name)
-  (checkcast "java/lang/String")
-  (invokespecial "com/tailrecursion/larquil/stage0/ClassFile" "<init>" "(Ljava/lang/String;)V")
+  (invoke 1)
   (store cf)
+  (load-function class_add_interface)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
   (sconst "com/tailrecursion/larquil/stage0/IFunction")
-  (invokevirtual "com/tailrecursion/larquil/stage0/ClassFile" "addInterface" "(Ljava/lang/String;)V")
+  (invoke 2)
+  (pop)
+  (load-function class_add_field)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
-  (iconst 25)
+  (lconst 25)
   (sconst "INSTANCE")
   (new "java/lang/StringBuilder")
   (dup)
@@ -449,7 +437,8 @@
   (sconst ";")
   (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/String;)Ljava/lang/StringBuilder;")
   (invokevirtual "java/lang/StringBuilder" "toString" "()Ljava/lang/String;")
-  (invokevirtual "com/tailrecursion/larquil/stage0/ClassFile" "addField" "(ILjava/lang/String;Ljava/lang/String;)V")
+  (invoke 4)
+  (pop)
   (load-function add_constructor)
   (load cf)
   (invoke 1)
@@ -457,14 +446,12 @@
   (load cf)
   (load class_name)
   (invoke 2)
-  (new "com/tailrecursion/larquil/stage0/MethodCode")
-  (dup)
+  (load-function method_code)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
-  (iconst 1)
+  (lconst 1)
   (sconst "invoke")
   (sconst "([Ljava/lang/Object;)Ljava/lang/Object;")
-  (invokespecial "com/tailrecursion/larquil/stage0/MethodCode" "<init>" "(Lcom/tailrecursion/larquil/stage0/ClassFile;ILjava/lang/String;Ljava/lang/String;)V")
+  (invoke 4)
   (store method)
   (load-function compile_state)
   (load method)
@@ -575,14 +562,15 @@
   (load method)
   (invoke 1)
   (pop)
+  (load-function finish_labels)
   (load method)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "finishLabels" "()V")
+  (invoke 1)
+  (pop)
+  (load-function class_add_method)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
   (load method)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
-  (invokevirtual "com/tailrecursion/larquil/stage0/ClassFile" "addMethod" "(Lcom/tailrecursion/larquil/stage0/MethodCode;)V")
+  (invoke 2)
+  (pop)
   (load cf)
   (return))
 
@@ -609,23 +597,22 @@
   (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/String;)Ljava/lang/StringBuilder;")
   (invokevirtual "java/lang/StringBuilder" "toString" "()Ljava/lang/String;")
   (store self_desc)
-  (new "com/tailrecursion/larquil/stage0/ClassFile")
-  (dup)
+  (load-function class_file)
   (load name)
-  (checkcast "java/lang/String")
-  (invokespecial "com/tailrecursion/larquil/stage0/ClassFile" "<init>" "(Ljava/lang/String;)V")
+  (invoke 1)
   (store cf)
+  (load-function class_add_interface)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
   (sconst "com/tailrecursion/larquil/stage0/IFunction")
-  (invokevirtual "com/tailrecursion/larquil/stage0/ClassFile" "addInterface" "(Ljava/lang/String;)V")
+  (invoke 2)
+  (pop)
+  (load-function class_add_field)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
-  (iconst 25)
+  (lconst 25)
   (sconst "INSTANCE")
   (load self_desc)
-  (checkcast "java/lang/String")
-  (invokevirtual "com/tailrecursion/larquil/stage0/ClassFile" "addField" "(ILjava/lang/String;Ljava/lang/String;)V")
+  (invoke 4)
+  (pop)
   (load-function add_constructor)
   (load cf)
   (invoke 1)
@@ -637,14 +624,12 @@
   (load cf)
   (load name)
   (invoke 2)
-  (new "com/tailrecursion/larquil/stage0/MethodCode")
-  (dup)
+  (load-function method_code)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
-  (iconst 1)
+  (lconst 1)
   (sconst "invoke")
   (sconst "([Ljava/lang/Object;)Ljava/lang/Object;")
-  (invokespecial "com/tailrecursion/larquil/stage0/MethodCode" "<init>" "(Lcom/tailrecursion/larquil/stage0/ClassFile;ILjava/lang/String;Ljava/lang/String;)V")
+  (invoke 4)
   (store method)
   (load-function emit_arity_check)
   (load method)
@@ -725,10 +710,10 @@
   (load method)
   (invoke 1)
   (pop)
+  (load-function class_add_method)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
   (load method)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
-  (invokevirtual "com/tailrecursion/larquil/stage0/ClassFile" "addMethod" "(Lcom/tailrecursion/larquil/stage0/MethodCode;)V")
+  (invoke 2)
+  (pop)
   (load cf)
   (return))
diff --git a/stage1/classfile.lql b/stage1/classfile.lql
new file mode 100644
index 0000000..47005da
--- /dev/null
+++ b/stage1/classfile.lql
@@ -0,0 +1,1643 @@
+; Larquil-owned JVM classfile and method assembly.
+
+(function rec_get (xs idx)
+  (load xs)
+  (checkcast "java/util/ArrayList")
+  (load idx)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (invokevirtual "java/util/ArrayList" "get" "(I)Ljava/lang/Object;")
+  (return))
+
+(function rec_set (xs idx value)
+  (load xs)
+  (checkcast "java/util/ArrayList")
+  (load idx)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (load value)
+  (invokevirtual "java/util/ArrayList" "set" "(ILjava/lang/Object;)Ljava/lang/Object;")
+  (pop)
+  (aconst-null)
+  (return))
+
+(function rec_add (xs value)
+  (load xs)
+  (checkcast "java/util/ArrayList")
+  (load value)
+  (invokevirtual "java/util/ArrayList" "add" "(Ljava/lang/Object;)Z")
+  (pop)
+  (aconst-null)
+  (return))
+
+(function new_list ()
+  (new "java/util/ArrayList")
+  (dup)
+  (invokespecial "java/util/ArrayList" "<init>" "()V")
+  (return))
+
+(function cp_entry (tag value)
+  (load-function pair)
+  (load tag)
+  (load value)
+  (invoke 2)
+  (return))
+
+(function cp_tag (entry)
+  (load-function pair_a)
+  (load entry)
+  (invoke 1)
+  (return))
+
+(function cp_value (entry)
+  (load-function pair_b)
+  (load entry)
+  (invoke 1)
+  (return))
+
+(function field_info (access name desc)
+  (new "java/util/ArrayList")
+  (dup)
+  (invokespecial "java/util/ArrayList" "<init>" "()V")
+  (store f)
+  (load-function rec_add)
+  (load f)
+  (load access)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load f)
+  (load name)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load f)
+  (load desc)
+  (invoke 2)
+  (pop)
+  (load f)
+  (return))
+
+(function field_access (f)
+  (load-function rec_get)
+  (load f)
+  (lconst 0)
+  (invoke 2)
+  (return))
+
+(function field_name (f)
+  (load-function rec_get)
+  (load f)
+  (lconst 1)
+  (invoke 2)
+  (return))
+
+(function field_desc (f)
+  (load-function rec_get)
+  (load f)
+  (lconst 2)
+  (invoke 2)
+  (return))
+
+(function branch_patch (label op_pos patch_pos)
+  (new "java/util/ArrayList")
+  (dup)
+  (invokespecial "java/util/ArrayList" "<init>" "()V")
+  (store p)
+  (load-function rec_add)
+  (load p)
+  (load label)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load p)
+  (load op_pos)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load p)
+  (load patch_pos)
+  (invoke 2)
+  (pop)
+  (load p)
+  (return))
+
+(function patch_label (p)
+  (load-function rec_get)
+  (load p)
+  (lconst 0)
+  (invoke 2)
+  (return))
+
+(function patch_op_pos (p)
+  (load-function rec_get)
+  (load p)
+  (lconst 1)
+  (invoke 2)
+  (return))
+
+(function patch_patch_pos (p)
+  (load-function rec_get)
+  (load p)
+  (lconst 2)
+  (invoke 2)
+  (return))
+
+(function key2 (prefix a)
+  (new "java/lang/StringBuilder")
+  (dup)
+  (invokespecial "java/lang/StringBuilder" "<init>" "()V")
+  (load prefix)
+  (checkcast "java/lang/String")
+  (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/String;)Ljava/lang/StringBuilder;")
+  (load a)
+  (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/Object;)Ljava/lang/StringBuilder;")
+  (invokevirtual "java/lang/StringBuilder" "toString" "()Ljava/lang/String;")
+  (return))
+
+(function key4 (prefix a b c)
+  (new "java/lang/StringBuilder")
+  (dup)
+  (invokespecial "java/lang/StringBuilder" "<init>" "()V")
+  (load prefix)
+  (checkcast "java/lang/String")
+  (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/String;)Ljava/lang/StringBuilder;")
+  (load a)
+  (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/Object;)Ljava/lang/StringBuilder;")
+  (sconst ":")
+  (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/String;)Ljava/lang/StringBuilder;")
+  (load b)
+  (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/Object;)Ljava/lang/StringBuilder;")
+  (sconst ":")
+  (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/String;)Ljava/lang/StringBuilder;")
+  (load c)
+  (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/Object;)Ljava/lang/StringBuilder;")
+  (invokevirtual "java/lang/StringBuilder" "toString" "()Ljava/lang/String;")
+  (return))
+
+(function key3 (prefix a b)
+  (new "java/lang/StringBuilder")
+  (dup)
+  (invokespecial "java/lang/StringBuilder" "<init>" "()V")
+  (load prefix)
+  (checkcast "java/lang/String")
+  (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/String;)Ljava/lang/StringBuilder;")
+  (load a)
+  (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/Object;)Ljava/lang/StringBuilder;")
+  (sconst ":")
+  (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/String;)Ljava/lang/StringBuilder;")
+  (load b)
+  (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/Object;)Ljava/lang/StringBuilder;")
+  (invokevirtual "java/lang/StringBuilder" "toString" "()Ljava/lang/String;")
+  (return))
+
+(function class_file (name)
+  (new "java/util/ArrayList")
+  (dup)
+  (invokespecial "java/util/ArrayList" "<init>" "()V")
+  (store cf)
+  (load-function rec_add)
+  (load cf)
+  (load name)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load cf)
+  (load-function new_list)
+  (invoke 0)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load cf)
+  (new "java/util/HashMap")
+  (dup)
+  (invokespecial "java/util/HashMap" "<init>" "()V")
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load cf)
+  (load-function new_list)
+  (invoke 0)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load cf)
+  (load-function new_list)
+  (invoke 0)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load cf)
+  (load-function new_list)
+  (invoke 0)
+  (invoke 2)
+  (pop)
+  (load-function cp_class)
+  (load cf)
+  (load name)
+  (invoke 2)
+  (pop)
+  (load-function cp_class)
+  (load cf)
+  (sconst "java/lang/Object")
+  (invoke 2)
+  (pop)
+  (load cf)
+  (return))
+
+(function class_name (cf)
+  (load-function rec_get)
+  (load cf)
+  (lconst 0)
+  (invoke 2)
+  (checkcast "java/lang/String")
+  (return))
+
+(function class_cp (cf)
+  (load-function rec_get)
+  (load cf)
+  (lconst 1)
+  (invoke 2)
+  (checkcast "java/util/ArrayList")
+  (return))
+
+(function class_cp_index (cf)
+  (load-function rec_get)
+  (load cf)
+  (lconst 2)
+  (invoke 2)
+  (checkcast "java/util/HashMap")
+  (return))
+
+(function class_fields (cf)
+  (load-function rec_get)
+  (load cf)
+  (lconst 3)
+  (invoke 2)
+  (checkcast "java/util/ArrayList")
+  (return))
+
+(function class_methods (cf)
+  (load-function rec_get)
+  (load cf)
+  (lconst 4)
+  (invoke 2)
+  (checkcast "java/util/ArrayList")
+  (return))
+
+(function class_interfaces (cf)
+  (load-function rec_get)
+  (load cf)
+  (lconst 5)
+  (invoke 2)
+  (checkcast "java/util/ArrayList")
+  (return))
+
+(function cp_lookup (cf key)
+  (load-function class_cp_index)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/HashMap")
+  (load key)
+  (checkcast "java/lang/String")
+  (invokevirtual "java/util/HashMap" "get" "(Ljava/lang/Object;)Ljava/lang/Object;")
+  (return))
+
+(function cp_store (cf key idx)
+  (load-function class_cp_index)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/HashMap")
+  (load key)
+  (checkcast "java/lang/String")
+  (load idx)
+  (invokevirtual "java/util/HashMap" "put" "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")
+  (pop)
+  (aconst-null)
+  (return))
+
+(function next_cp_index (cf)
+  (load-function class_cp)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (invokevirtual "java/util/ArrayList" "size" "()I")
+  (i2l)
+  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
+  (lconst 1)
+  (ladd)
+  (return))
+
+(function cp_utf8 (cf value)
+  (load-function key2)
+  (sconst "U:")
+  (load value)
+  (invoke 2)
+  (store key)
+  (load-function cp_lookup)
+  (load cf)
+  (load key)
+  (invoke 2)
+  (store got)
+  (load got)
+  (jump-if-false miss)
+  (load got)
+  (return)
+  (label miss)
+  (load-function next_cp_index)
+  (load cf)
+  (invoke 1)
+  (store idx)
+  (load-function class_cp)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (load-function cp_entry)
+  (lconst 1)
+  (load value)
+  (invoke 2)
+  (invokevirtual "java/util/ArrayList" "add" "(Ljava/lang/Object;)Z")
+  (pop)
+  (load-function cp_store)
+  (load cf)
+  (load key)
+  (load idx)
+  (invoke 3)
+  (pop)
+  (load idx)
+  (return))
+
+(function cp_class (cf cls)
+  (load-function key2)
+  (sconst "C:")
+  (load cls)
+  (invoke 2)
+  (store key)
+  (load-function cp_lookup)
+  (load cf)
+  (load key)
+  (invoke 2)
+  (store got)
+  (load got)
+  (jump-if-false miss)
+  (load got)
+  (return)
+  (label miss)
+  (load-function cp_utf8)
+  (load cf)
+  (load cls)
+  (invoke 2)
+  (store name_idx)
+  (load-function next_cp_index)
+  (load cf)
+  (invoke 1)
+  (store idx)
+  (load-function class_cp)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (load-function cp_entry)
+  (lconst 7)
+  (load name_idx)
+  (invoke 2)
+  (invokevirtual "java/util/ArrayList" "add" "(Ljava/lang/Object;)Z")
+  (pop)
+  (load-function cp_store)
+  (load cf)
+  (load key)
+  (load idx)
+  (invoke 3)
+  (pop)
+  (load idx)
+  (return))
+
+(function cp_long (cf value)
+  (load-function key2)
+  (sconst "J:")
+  (load value)
+  (invoke 2)
+  (store key)
+  (load-function cp_lookup)
+  (load cf)
+  (load key)
+  (invoke 2)
+  (store got)
+  (load got)
+  (jump-if-false miss)
+  (load got)
+  (return)
+  (label miss)
+  (load-function next_cp_index)
+  (load cf)
+  (invoke 1)
+  (store idx)
+  (load-function class_cp)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (load-function cp_entry)
+  (lconst 5)
+  (load value)
+  (invoke 2)
+  (invokevirtual "java/util/ArrayList" "add" "(Ljava/lang/Object;)Z")
+  (pop)
+  (load-function class_cp)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (aconst-null)
+  (invokevirtual "java/util/ArrayList" "add" "(Ljava/lang/Object;)Z")
+  (pop)
+  (load-function cp_store)
+  (load cf)
+  (load key)
+  (load idx)
+  (invoke 3)
+  (pop)
+  (load idx)
+  (return))
+
+(function cp_string (cf value)
+  (load-function key2)
+  (sconst "S:")
+  (load value)
+  (invoke 2)
+  (store key)
+  (load-function cp_lookup)
+  (load cf)
+  (load key)
+  (invoke 2)
+  (store got)
+  (load got)
+  (jump-if-false miss)
+  (load got)
+  (return)
+  (label miss)
+  (load-function cp_utf8)
+  (load cf)
+  (load value)
+  (invoke 2)
+  (store utf8_idx)
+  (load-function next_cp_index)
+  (load cf)
+  (invoke 1)
+  (store idx)
+  (load-function class_cp)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (load-function cp_entry)
+  (lconst 8)
+  (load utf8_idx)
+  (invoke 2)
+  (invokevirtual "java/util/ArrayList" "add" "(Ljava/lang/Object;)Z")
+  (pop)
+  (load-function cp_store)
+  (load cf)
+  (load key)
+  (load idx)
+  (invoke 3)
+  (pop)
+  (load idx)
+  (return))
+
+(function cp_name_type (cf name desc)
+  (load-function key3)
+  (sconst "NT:")
+  (load name)
+  (load desc)
+  (invoke 3)
+  (store key)
+  (load-function cp_lookup)
+  (load cf)
+  (load key)
+  (invoke 2)
+  (store got)
+  (load got)
+  (jump-if-false miss)
+  (load got)
+  (return)
+  (label miss)
+  (load-function cp_utf8)
+  (load cf)
+  (load name)
+  (invoke 2)
+  (store name_idx)
+  (load-function cp_utf8)
+  (load cf)
+  (load desc)
+  (invoke 2)
+  (store desc_idx)
+  (load-function next_cp_index)
+  (load cf)
+  (invoke 1)
+  (store idx)
+  (load-function class_cp)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (load-function cp_entry)
+  (lconst 12)
+  (load-function pair)
+  (load name_idx)
+  (load desc_idx)
+  (invoke 2)
+  (invoke 2)
+  (invokevirtual "java/util/ArrayList" "add" "(Ljava/lang/Object;)Z")
+  (pop)
+  (load-function cp_store)
+  (load cf)
+  (load key)
+  (load idx)
+  (invoke 3)
+  (pop)
+  (load idx)
+  (return))
+
+(function cp_ref (cf tag prefix cls name desc)
+  (load-function key4)
+  (load prefix)
+  (load cls)
+  (load name)
+  (load desc)
+  (invoke 4)
+  (store key)
+  (load-function cp_lookup)
+  (load cf)
+  (load key)
+  (invoke 2)
+  (store got)
+  (load got)
+  (jump-if-false miss)
+  (load got)
+  (return)
+  (label miss)
+  (load-function cp_class)
+  (load cf)
+  (load cls)
+  (invoke 2)
+  (store class_idx)
+  (load-function cp_name_type)
+  (load cf)
+  (load name)
+  (load desc)
+  (invoke 3)
+  (store nt_idx)
+  (load-function next_cp_index)
+  (load cf)
+  (invoke 1)
+  (store idx)
+  (load-function class_cp)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (load-function cp_entry)
+  (load tag)
+  (load-function pair)
+  (load class_idx)
+  (load nt_idx)
+  (invoke 2)
+  (invoke 2)
+  (invokevirtual "java/util/ArrayList" "add" "(Ljava/lang/Object;)Z")
+  (pop)
+  (load-function cp_store)
+  (load cf)
+  (load key)
+  (load idx)
+  (invoke 3)
+  (pop)
+  (load idx)
+  (return))
+
+(function cp_fieldref (cf cls name desc)
+  (load-function cp_ref)
+  (load cf)
+  (lconst 9)
+  (sconst "F:")
+  (load cls)
+  (load name)
+  (load desc)
+  (invoke 6)
+  (return))
+
+(function cp_methodref (cf cls name desc)
+  (load-function cp_ref)
+  (load cf)
+  (lconst 10)
+  (sconst "M:")
+  (load cls)
+  (load name)
+  (load desc)
+  (invoke 6)
+  (return))
+
+(function cp_interface_methodref (cf cls name desc)
+  (load-function cp_ref)
+  (load cf)
+  (lconst 11)
+  (sconst "IM:")
+  (load cls)
+  (load name)
+  (load desc)
+  (invoke 6)
+  (return))
+
+(function class_add_interface (cf iface)
+  (load-function class_interfaces)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (load-function cp_class)
+  (load cf)
+  (load iface)
+  (invoke 2)
+  (invokevirtual "java/util/ArrayList" "add" "(Ljava/lang/Object;)Z")
+  (pop)
+  (aconst-null)
+  (return))
+
+(function class_add_field (cf access name desc)
+  (load-function class_fields)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (load-function field_info)
+  (load access)
+  (load-function cp_utf8)
+  (load cf)
+  (load name)
+  (invoke 2)
+  (load-function cp_utf8)
+  (load cf)
+  (load desc)
+  (invoke 2)
+  (invoke 3)
+  (invokevirtual "java/util/ArrayList" "add" "(Ljava/lang/Object;)Z")
+  (pop)
+  (aconst-null)
+  (return))
+
+(function class_add_method (cf method)
+  (load-function class_methods)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (load method)
+  (invokevirtual "java/util/ArrayList" "add" "(Ljava/lang/Object;)Z")
+  (pop)
+  (aconst-null)
+  (return))
+
+(function writer ()
+  (new "java/io/ByteArrayOutputStream")
+  (dup)
+  (invokespecial "java/io/ByteArrayOutputStream" "<init>" "()V")
+  (store out)
+  (new "java/io/DataOutputStream")
+  (dup)
+  (load out)
+  (checkcast "java/io/OutputStream")
+  (invokespecial "java/io/DataOutputStream" "<init>" "(Ljava/io/OutputStream;)V")
+  (store data)
+  (load-function pair)
+  (load out)
+  (load data)
+  (invoke 2)
+  (return))
+
+(function writer_out (w)
+  (load-function pair_a)
+  (load w)
+  (invoke 1)
+  (checkcast "java/io/ByteArrayOutputStream")
+  (return))
+
+(function writer_data (w)
+  (load-function pair_b)
+  (load w)
+  (invoke 1)
+  (checkcast "java/io/DataOutputStream")
+  (return))
+
+(function write_u1 (w value)
+  (load-function writer_data)
+  (load w)
+  (invoke 1)
+  (checkcast "java/io/DataOutputStream")
+  (load value)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (invokevirtual "java/io/DataOutputStream" "writeByte" "(I)V")
+  (aconst-null)
+  (return))
+
+(function write_u2 (w value)
+  (load-function writer_data)
+  (load w)
+  (invoke 1)
+  (checkcast "java/io/DataOutputStream")
+  (load value)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (invokevirtual "java/io/DataOutputStream" "writeShort" "(I)V")
+  (aconst-null)
+  (return))
+
+(function write_u4 (w value)
+  (load-function writer_data)
+  (load w)
+  (invoke 1)
+  (checkcast "java/io/DataOutputStream")
+  (load value)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (invokevirtual "java/io/DataOutputStream" "writeInt" "(I)V")
+  (aconst-null)
+  (return))
+
+(function write_long (w value)
+  (load-function writer_data)
+  (load w)
+  (invoke 1)
+  (checkcast "java/io/DataOutputStream")
+  (load value)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "longValue" "()J")
+  (invokevirtual "java/io/DataOutputStream" "writeLong" "(J)V")
+  (aconst-null)
+  (return))
+
+(function write_bytes (w bytes)
+  (load-function writer_data)
+  (load w)
+  (invoke 1)
+  (checkcast "java/io/DataOutputStream")
+  (load bytes)
+  (checkcast "[B")
+  (invokevirtual "java/io/DataOutputStream" "write" "([B)V")
+  (aconst-null)
+  (return))
+
+(function byte_array_length (bytes)
+  (load bytes)
+  (invokestatic "java/lang/reflect/Array" "getLength" "(Ljava/lang/Object;)I")
+  (i2l)
+  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
+  (return))
+
+(function writer_bytes (w)
+  (load-function writer_data)
+  (load w)
+  (invoke 1)
+  (checkcast "java/io/DataOutputStream")
+  (invokevirtual "java/io/DataOutputStream" "flush" "()V")
+  (load-function writer_out)
+  (load w)
+  (invoke 1)
+  (checkcast "java/io/ByteArrayOutputStream")
+  (invokevirtual "java/io/ByteArrayOutputStream" "toByteArray" "()[B")
+  (return))
+
+(function write_cp (w entry)
+  (load-function write_u1)
+  (load w)
+  (load-function cp_tag)
+  (load entry)
+  (invoke 1)
+  (invoke 2)
+  (pop)
+  (load-function cp_tag)
+  (load entry)
+  (invoke 1)
+  (store tag)
+  (load tag)
+  (lconst 1)
+  (invokevirtual "java/lang/Object" "equals" "(Ljava/lang/Object;)Z")
+  (ifeq try_class_string)
+  (load-function cp_value)
+  (load entry)
+  (invoke 1)
+  (checkcast "java/lang/String")
+  (getstatic "java/nio/charset/StandardCharsets" "UTF_8" "Ljava/nio/charset/Charset;")
+  (invokevirtual "java/lang/String" "getBytes" "(Ljava/nio/charset/Charset;)[B")
+  (store bytes)
+  (load-function write_u2)
+  (load w)
+  (load-function byte_array_length)
+  (load bytes)
+  (invoke 1)
+  (invoke 2)
+  (pop)
+  (load-function write_bytes)
+  (load w)
+  (load bytes)
+  (invoke 2)
+  (return)
+  (label try_class_string)
+  (load tag)
+  (lconst 7)
+  (invokevirtual "java/lang/Object" "equals" "(Ljava/lang/Object;)Z")
+  (ifne write_one_index)
+  (load tag)
+  (lconst 8)
+  (invokevirtual "java/lang/Object" "equals" "(Ljava/lang/Object;)Z")
+  (ifeq try_long)
+  (label write_one_index)
+  (load-function write_u2)
+  (load w)
+  (load-function cp_value)
+  (load entry)
+  (invoke 1)
+  (invoke 2)
+  (return)
+  (label try_long)
+  (load tag)
+  (lconst 5)
+  (invokevirtual "java/lang/Object" "equals" "(Ljava/lang/Object;)Z")
+  (ifeq write_pair)
+  (load-function write_long)
+  (load w)
+  (load-function cp_value)
+  (load entry)
+  (invoke 1)
+  (invoke 2)
+  (return)
+  (label write_pair)
+  (load-function cp_value)
+  (load entry)
+  (invoke 1)
+  (store p)
+  (load-function write_u2)
+  (load w)
+  (load-function pair_a)
+  (load p)
+  (invoke 1)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (load-function pair_b)
+  (load p)
+  (invoke 1)
+  (invoke 2)
+  (return))
+
+(function class_bytes (cf)
+  (load-function cp_utf8)
+  (load cf)
+  (sconst "Code")
+  (invoke 2)
+  (pop)
+  (load-function writer)
+  (invoke 0)
+  (store w)
+  (load-function write_u4)
+  (load w)
+  (lconst 3405691582)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (lconst 0)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (lconst 49)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (load-function class_cp)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (invokevirtual "java/util/ArrayList" "size" "()I")
+  (i2l)
+  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
+  (lconst 1)
+  (ladd)
+  (invoke 2)
+  (pop)
+  (lconst 0)
+  (store i)
+  (label cp_loop)
+  (load i)
+  (load-function class_cp)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (invokevirtual "java/util/ArrayList" "size" "()I")
+  (i2l)
+  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
+  (llt)
+  (jump-if-false cp_done)
+  (load-function class_cp)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (load i)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (invokevirtual "java/util/ArrayList" "get" "(I)Ljava/lang/Object;")
+  (store entry)
+  (load entry)
+  (jump-if-false cp_next)
+  (load-function write_cp)
+  (load w)
+  (load entry)
+  (invoke 2)
+  (pop)
+  (label cp_next)
+  (load i)
+  (lconst 1)
+  (ladd)
+  (store i)
+  (jump cp_loop)
+  (label cp_done)
+  (load-function write_u2)
+  (load w)
+  (lconst 49)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (load-function cp_class)
+  (load cf)
+  (load-function class_name)
+  (load cf)
+  (invoke 1)
+  (invoke 2)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (load-function cp_class)
+  (load cf)
+  (sconst "java/lang/Object")
+  (invoke 2)
+  (invoke 2)
+  (pop)
+  (load-function write_list_u2)
+  (load w)
+  (load-function class_interfaces)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (invoke 2)
+  (pop)
+  (load-function write_fields)
+  (load w)
+  (load cf)
+  (invoke 2)
+  (pop)
+  (load-function write_methods)
+  (load w)
+  (load cf)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (lconst 0)
+  (invoke 2)
+  (pop)
+  (load-function writer_bytes)
+  (load w)
+  (invoke 1)
+  (return))
+
+(function write_list_u2 (w xs)
+  (load-function write_u2)
+  (load w)
+  (load xs)
+  (checkcast "java/util/ArrayList")
+  (invokevirtual "java/util/ArrayList" "size" "()I")
+  (i2l)
+  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
+  (invoke 2)
+  (pop)
+  (lconst 0)
+  (store i)
+  (label loop)
+  (load i)
+  (load xs)
+  (checkcast "java/util/ArrayList")
+  (invokevirtual "java/util/ArrayList" "size" "()I")
+  (i2l)
+  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
+  (llt)
+  (jump-if-false done)
+  (load-function write_u2)
+  (load w)
+  (load xs)
+  (checkcast "java/util/ArrayList")
+  (load i)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (invokevirtual "java/util/ArrayList" "get" "(I)Ljava/lang/Object;")
+  (invoke 2)
+  (pop)
+  (load i)
+  (lconst 1)
+  (ladd)
+  (store i)
+  (jump loop)
+  (label done)
+  (aconst-null)
+  (return))
+
+(function write_fields (w cf)
+  (load-function class_fields)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (store fields)
+  (load-function write_u2)
+  (load w)
+  (load fields)
+  (checkcast "java/util/ArrayList")
+  (invokevirtual "java/util/ArrayList" "size" "()I")
+  (i2l)
+  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
+  (invoke 2)
+  (pop)
+  (lconst 0)
+  (store i)
+  (label loop)
+  (load i)
+  (load fields)
+  (checkcast "java/util/ArrayList")
+  (invokevirtual "java/util/ArrayList" "size" "()I")
+  (i2l)
+  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
+  (llt)
+  (jump-if-false done)
+  (load fields)
+  (checkcast "java/util/ArrayList")
+  (load i)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (invokevirtual "java/util/ArrayList" "get" "(I)Ljava/lang/Object;")
+  (store f)
+  (load-function write_u2)
+  (load w)
+  (load-function field_access)
+  (load f)
+  (invoke 1)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (load-function field_name)
+  (load f)
+  (invoke 1)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (load-function field_desc)
+  (load f)
+  (invoke 1)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (lconst 0)
+  (invoke 2)
+  (pop)
+  (load i)
+  (lconst 1)
+  (ladd)
+  (store i)
+  (jump loop)
+  (label done)
+  (aconst-null)
+  (return))
+
+(function write_methods (w cf)
+  (load-function class_methods)
+  (load cf)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (store methods)
+  (load-function write_u2)
+  (load w)
+  (load methods)
+  (checkcast "java/util/ArrayList")
+  (invokevirtual "java/util/ArrayList" "size" "()I")
+  (i2l)
+  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
+  (invoke 2)
+  (pop)
+  (lconst 0)
+  (store i)
+  (label loop)
+  (load i)
+  (load methods)
+  (checkcast "java/util/ArrayList")
+  (invokevirtual "java/util/ArrayList" "size" "()I")
+  (i2l)
+  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
+  (llt)
+  (jump-if-false done)
+  (load-function method_write)
+  (load methods)
+  (checkcast "java/util/ArrayList")
+  (load i)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (invokevirtual "java/util/ArrayList" "get" "(I)Ljava/lang/Object;")
+  (load w)
+  (invoke 2)
+  (pop)
+  (load i)
+  (lconst 1)
+  (ladd)
+  (store i)
+  (jump loop)
+  (label done)
+  (aconst-null)
+  (return))
+
+(function method_code (cf access name desc)
+  (new "java/util/ArrayList")
+  (dup)
+  (invokespecial "java/util/ArrayList" "<init>" "()V")
+  (store m)
+  (load-function rec_add)
+  (load m)
+  (load cf)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load m)
+  (load access)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load m)
+  (load-function cp_utf8)
+  (load cf)
+  (load name)
+  (invoke 2)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load m)
+  (load-function cp_utf8)
+  (load cf)
+  (load desc)
+  (invoke 2)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load m)
+  (lconst 65535)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (invokestatic "java/nio/ByteBuffer" "allocate" "(I)Ljava/nio/ByteBuffer;")
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load m)
+  (load-function new_list)
+  (invoke 0)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load m)
+  (load-function new_list)
+  (invoke 0)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load m)
+  (lconst 64)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load m)
+  (lconst 2)
+  (invoke 2)
+  (pop)
+  (load-function rec_add)
+  (load m)
+  (lconst 0)
+  (invoke 2)
+  (pop)
+  (load m)
+  (return))
+
+(function method_cf (m)
+  (load-function rec_get)
+  (load m)
+  (lconst 0)
+  (invoke 2)
+  (return))
+
+(function method_access (m)
+  (load-function rec_get)
+  (load m)
+  (lconst 1)
+  (invoke 2)
+  (return))
+
+(function method_name_index (m)
+  (load-function rec_get)
+  (load m)
+  (lconst 2)
+  (invoke 2)
+  (return))
+
+(function method_desc_index (m)
+  (load-function rec_get)
+  (load m)
+  (lconst 3)
+  (invoke 2)
+  (return))
+
+(function method_code_buffer (m)
+  (load-function rec_get)
+  (load m)
+  (lconst 4)
+  (invoke 2)
+  (checkcast "java/nio/ByteBuffer")
+  (return))
+
+(function method_labels (m)
+  (load-function rec_get)
+  (load m)
+  (lconst 5)
+  (invoke 2)
+  (checkcast "java/util/ArrayList")
+  (return))
+
+(function method_patches (m)
+  (load-function rec_get)
+  (load m)
+  (lconst 6)
+  (invoke 2)
+  (checkcast "java/util/ArrayList")
+  (return))
+
+(function method_max_stack (m)
+  (load-function rec_get)
+  (load m)
+  (lconst 7)
+  (invoke 2)
+  (return))
+
+(function method_max_locals (m)
+  (load-function rec_get)
+  (load m)
+  (lconst 8)
+  (invoke 2)
+  (return))
+
+(function method_set_max_locals (m value)
+  (load-function rec_set)
+  (load m)
+  (lconst 8)
+  (load value)
+  (invoke 3)
+  (return))
+
+(function method_next_internal (m)
+  (load-function rec_get)
+  (load m)
+  (lconst 9)
+  (invoke 2)
+  (store v)
+  (load-function rec_set)
+  (load m)
+  (lconst 9)
+  (load v)
+  (lconst 1)
+  (ladd)
+  (invoke 3)
+  (pop)
+  (load v)
+  (return))
+
+(function code_pos (m)
+  (load-function method_code_buffer)
+  (load m)
+  (invoke 1)
+  (checkcast "java/nio/ByteBuffer")
+  (invokevirtual "java/nio/ByteBuffer" "position" "()I")
+  (i2l)
+  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
+  (return))
+
+(function code_put_byte (m value)
+  (load-function method_code_buffer)
+  (load m)
+  (invoke 1)
+  (checkcast "java/nio/ByteBuffer")
+  (load value)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (invokevirtual "java/nio/ByteBuffer" "put" "(B)Ljava/nio/ByteBuffer;")
+  (pop)
+  (aconst-null)
+  (return))
+
+(function code_put_short (m value)
+  (load-function method_code_buffer)
+  (load m)
+  (invoke 1)
+  (checkcast "java/nio/ByteBuffer")
+  (load value)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (invokevirtual "java/nio/ByteBuffer" "putShort" "(S)Ljava/nio/ByteBuffer;")
+  (pop)
+  (aconst-null)
+  (return))
+
+(function code_patch_short (m pos value)
+  (load-function method_code_buffer)
+  (load m)
+  (invoke 1)
+  (checkcast "java/nio/ByteBuffer")
+  (load pos)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (load value)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (invokevirtual "java/nio/ByteBuffer" "putShort" "(IS)Ljava/nio/ByteBuffer;")
+  (pop)
+  (aconst-null)
+  (return))
+
+(function method_code_bytes (m)
+  (load-function method_code_buffer)
+  (load m)
+  (invoke 1)
+  (checkcast "java/nio/ByteBuffer")
+  (invokevirtual "java/nio/ByteBuffer" "array" "()[B")
+  (load-function code_pos)
+  (load m)
+  (invoke 1)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (invokestatic "java/util/Arrays" "copyOf" "([BI)[B")
+  (return))
+
+(function method_lookup_label (m label)
+  (load-function method_labels)
+  (load m)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (invokevirtual "java/util/ArrayList" "size" "()I")
+  (i2l)
+  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
+  (lconst 1)
+  (lsub)
+  (store i)
+  (label loop)
+  (load i)
+  (lconst 0)
+  (llt)
+  (jump-if-false check)
+  (aconst-null)
+  (return)
+  (label check)
+  (load-function method_labels)
+  (load m)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (load i)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (invokevirtual "java/util/ArrayList" "get" "(I)Ljava/lang/Object;")
+  (store p)
+  (load label)
+  (load-function pair_a)
+  (load p)
+  (invoke 1)
+  (invokevirtual "java/lang/Object" "equals" "(Ljava/lang/Object;)Z")
+  (ifeq next)
+  (load-function pair_b)
+  (load p)
+  (invoke 1)
+  (return)
+  (label next)
+  (load i)
+  (lconst 1)
+  (lsub)
+  (store i)
+  (jump loop)
+  (aconst-null)
+  (return))
+
+(function method_label (m label)
+  (load-function method_lookup_label)
+  (load m)
+  (load label)
+  (invoke 2)
+  (jump-if-false ok)
+  (new "java/lang/RuntimeException")
+  (dup)
+  (invokespecial "java/lang/RuntimeException" "<init>" "()V")
+  (athrow)
+  (label ok)
+  (load-function method_labels)
+  (load m)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (load-function pair)
+  (load label)
+  (load-function code_pos)
+  (load m)
+  (invoke 1)
+  (invoke 2)
+  (invokevirtual "java/util/ArrayList" "add" "(Ljava/lang/Object;)Z")
+  (pop)
+  (aconst-null)
+  (return))
+
+(function method_branch (m opcode label)
+  (load-function code_pos)
+  (load m)
+  (invoke 1)
+  (store op_pos)
+  (load-function code_put_byte)
+  (load m)
+  (load opcode)
+  (invoke 2)
+  (pop)
+  (load-function code_pos)
+  (load m)
+  (invoke 1)
+  (store patch_pos)
+  (load-function code_put_short)
+  (load m)
+  (lconst 0)
+  (invoke 2)
+  (pop)
+  (load-function method_patches)
+  (load m)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (load-function branch_patch)
+  (load label)
+  (load op_pos)
+  (load patch_pos)
+  (invoke 3)
+  (invokevirtual "java/util/ArrayList" "add" "(Ljava/lang/Object;)Z")
+  (pop)
+  (aconst-null)
+  (return))
+
+(function finish_labels (m)
+  (lconst 0)
+  (store i)
+  (label loop)
+  (load i)
+  (load-function method_patches)
+  (load m)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (invokevirtual "java/util/ArrayList" "size" "()I")
+  (i2l)
+  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
+  (llt)
+  (jump-if-false done)
+  (load-function method_patches)
+  (load m)
+  (invoke 1)
+  (checkcast "java/util/ArrayList")
+  (load i)
+  (checkcast "java/lang/Long")
+  (invokevirtual "java/lang/Long" "intValue" "()I")
+  (invokevirtual "java/util/ArrayList" "get" "(I)Ljava/lang/Object;")
+  (store p)
+  (load-function method_lookup_label)
+  (load m)
+  (load-function patch_label)
+  (load p)
+  (invoke 1)
+  (invoke 2)
+  (store target)
+  (load target)
+  (jump-if-false bad)
+  (load-function code_patch_short)
+  (load m)
+  (load-function patch_patch_pos)
+  (load p)
+  (invoke 1)
+  (load target)
+  (checkcast "java/lang/Long")
+  (load-function patch_op_pos)
+  (load p)
+  (invoke 1)
+  (checkcast "java/lang/Long")
+  (lsub)
+  (invoke 3)
+  (pop)
+  (load i)
+  (lconst 1)
+  (ladd)
+  (store i)
+  (jump loop)
+  (label bad)
+  (new "java/lang/RuntimeException")
+  (dup)
+  (invokespecial "java/lang/RuntimeException" "<init>" "()V")
+  (athrow)
+  (label done)
+  (aconst-null)
+  (return))
+
+(function method_write (m w)
+  (load-function finish_labels)
+  (load m)
+  (invoke 1)
+  (pop)
+  (load-function method_code_bytes)
+  (load m)
+  (invoke 1)
+  (store bytes)
+  (load-function write_u2)
+  (load w)
+  (load-function method_access)
+  (load m)
+  (invoke 1)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (load-function method_name_index)
+  (load m)
+  (invoke 1)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (load-function method_desc_index)
+  (load m)
+  (invoke 1)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (lconst 1)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (load-function cp_utf8)
+  (load-function method_cf)
+  (load m)
+  (invoke 1)
+  (sconst "Code")
+  (invoke 2)
+  (invoke 2)
+  (pop)
+  (load-function write_u4)
+  (load w)
+  (load-function byte_array_length)
+  (load bytes)
+  (invoke 1)
+  (lconst 12)
+  (ladd)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (load-function method_max_stack)
+  (load m)
+  (invoke 1)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (load-function method_max_locals)
+  (load m)
+  (invoke 1)
+  (invoke 2)
+  (pop)
+  (load-function write_u4)
+  (load w)
+  (load-function byte_array_length)
+  (load bytes)
+  (invoke 1)
+  (invoke 2)
+  (pop)
+  (load-function write_bytes)
+  (load w)
+  (load bytes)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (lconst 0)
+  (invoke 2)
+  (pop)
+  (load-function write_u2)
+  (load w)
+  (lconst 0)
+  (invoke 2)
+  (return))
diff --git a/stage1/compiler.lql b/stage1/compiler.lql
index 0074fd9..eb6274a 100644
--- a/stage1/compiler.lql
+++ b/stage1/compiler.lql
@@ -15,9 +15,10 @@
   (new "java/lang/StringBuilder")
   (dup)
   (invokespecial "java/lang/StringBuilder" "<init>" "()V")
+  (load-function class_name)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
-  (getfield "com/tailrecursion/larquil/stage0/ClassFile" "name" "Ljava/lang/String;")
+  (invoke 1)
+  (checkcast "java/lang/String")
   (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/String;)Ljava/lang/StringBuilder;")
   (sconst ".class")
   (invokevirtual "java/lang/StringBuilder" "append" "(Ljava/lang/String;)Ljava/lang/StringBuilder;")
@@ -42,9 +43,10 @@
   (load file)
   (checkcast "java/io/File")
   (invokevirtual "java/io/File" "toPath" "()Ljava/nio/file/Path;")
+  (load-function class_bytes)
   (load cf)
-  (checkcast "com/tailrecursion/larquil/stage0/ClassFile")
-  (invokevirtual "com/tailrecursion/larquil/stage0/ClassFile" "bytes" "()[B")
+  (invoke 1)
+  (checkcast "[B")
   (iconst 0)
   (anewarray "java/nio/file/OpenOption")
   (invokestatic "java/nio/file/Files" "write" "(Ljava/nio/file/Path;[B[Ljava/nio/file/OpenOption;)Ljava/nio/file/Path;")
diff --git a/stage1/emit.lql b/stage1/emit.lql
index c35770d..f464735 100644
--- a/stage1/emit.lql
+++ b/stage1/emit.lql
@@ -1,256 +1,327 @@
-; First Stage 1 compiler chunk: bytecode emission helpers.
-; These functions operate on the Stage 0 MethodCode object for now.
+; Stage 1 bytecode emission helpers backed by Larquil-owned classfile data.
 
 (function emit_u1 (m opcode)
+  (load-function code_put_byte)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
   (load opcode)
-  (checkcast "java/lang/Long")
-  (invokevirtual "java/lang/Long" "intValue" "()I")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "u1" "(I)V")
+  (invoke 2)
   (lconst 0)
   (return))
 
 (function emit_u2 (m value)
+  (load-function code_put_short)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
   (load value)
-  (checkcast "java/lang/Long")
-  (invokevirtual "java/lang/Long" "intValue" "()I")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "u2" "(I)V")
+  (invoke 2)
   (lconst 0)
   (return))
 
 (function emit_push_int (m value)
+  (load-function emit_u1)
+  (load m)
+  (lconst 17)
+  (invoke 2)
+  (pop)
+  (load-function emit_u2)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
   (load value)
-  (checkcast "java/lang/Long")
-  (invokevirtual "java/lang/Long" "intValue" "()I")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "pushInt" "(I)V")
+  (invoke 2)
   (lconst 0)
   (return))
 
 (function emit_aload (m slot)
+  (load-function emit_u1)
+  (load m)
+  (lconst 196)
+  (invoke 2)
+  (pop)
+  (load-function emit_u1)
+  (load m)
+  (lconst 25)
+  (invoke 2)
+  (pop)
+  (load-function emit_u2)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
   (load slot)
-  (checkcast "java/lang/Long")
-  (invokevirtual "java/lang/Long" "intValue" "()I")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "aload" "(I)V")
+  (invoke 2)
   (lconst 0)
   (return))
 
 (function emit_astore (m slot)
+  (load-function emit_u1)
+  (load m)
+  (lconst 196)
+  (invoke 2)
+  (pop)
+  (load-function emit_u1)
+  (load m)
+  (lconst 58)
+  (invoke 2)
+  (pop)
+  (load-function emit_u2)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
   (load slot)
-  (checkcast "java/lang/Long")
-  (invokevirtual "java/lang/Long" "intValue" "()I")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "astore" "(I)V")
+  (invoke 2)
   (lconst 0)
   (return))
 
 (function emit_lconst (m value)
+  (load-function emit_u1)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
+  (lconst 20)
+  (invoke 2)
+  (pop)
+  (load-function emit_u2)
+  (load m)
+  (load-function cp_long)
+  (load-function method_cf)
+  (load m)
+  (invoke 1)
   (load value)
-  (checkcast "java/lang/Long")
-  (invokevirtual "java/lang/Long" "longValue" "()J")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "lconst" "(J)V")
+  (invoke 2)
+  (invoke 2)
+  (pop)
+  (load-function emit_invokestatic)
+  (load m)
+  (sconst "java/lang/Long")
+  (sconst "valueOf")
+  (sconst "(J)Ljava/lang/Long;")
+  (invoke 4)
   (lconst 0)
   (return))
 
 (function emit_sconst (m value)
+  (load-function emit_u1)
+  (load m)
+  (lconst 19)
+  (invoke 2)
+  (pop)
+  (load-function emit_u2)
+  (load m)
+  (load-function cp_string)
+  (load-function method_cf)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
+  (invoke 1)
   (load value)
-  (checkcast "java/lang/String")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "sconst" "(Ljava/lang/String;)V")
+  (invoke 2)
+  (invoke 2)
+  (lconst 0)
+  (return))
+
+(function emit_ref2 (m opcode idx)
+  (load-function emit_u1)
+  (load m)
+  (load opcode)
+  (invoke 2)
+  (pop)
+  (load-function emit_u2)
+  (load m)
+  (load idx)
+  (invoke 2)
   (lconst 0)
   (return))
 
 (function emit_getstatic (m owner name descriptor)
+  (load-function emit_ref2)
+  (load m)
+  (lconst 178)
+  (load-function cp_fieldref)
+  (load-function method_cf)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
+  (invoke 1)
   (load owner)
-  (checkcast "java/lang/String")
   (load name)
-  (checkcast "java/lang/String")
   (load descriptor)
-  (checkcast "java/lang/String")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "getstatic" "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V")
-  (lconst 0)
+  (invoke 4)
+  (invoke 3)
   (return))
 
 (function emit_putstatic (m owner name descriptor)
+  (load-function emit_ref2)
+  (load m)
+  (lconst 179)
+  (load-function cp_fieldref)
+  (load-function method_cf)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
+  (invoke 1)
   (load owner)
-  (checkcast "java/lang/String")
   (load name)
-  (checkcast "java/lang/String")
   (load descriptor)
-  (checkcast "java/lang/String")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "putstatic" "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V")
-  (lconst 0)
+  (invoke 4)
+  (invoke 3)
   (return))
 
 (function emit_getfield (m owner name descriptor)
+  (load-function emit_ref2)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
+  (lconst 180)
+  (load-function cp_fieldref)
+  (load-function method_cf)
+  (load m)
+  (invoke 1)
   (load owner)
-  (checkcast "java/lang/String")
   (load name)
-  (checkcast "java/lang/String")
   (load descriptor)
-  (checkcast "java/lang/String")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "getfield" "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V")
-  (lconst 0)
+  (invoke 4)
+  (invoke 3)
   (return))
 
 (function emit_putfield (m owner name descriptor)
+  (load-function emit_ref2)
+  (load m)
+  (lconst 181)
+  (load-function cp_fieldref)
+  (load-function method_cf)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
+  (invoke 1)
   (load owner)
-  (checkcast "java/lang/String")
   (load name)
-  (checkcast "java/lang/String")
   (load descriptor)
-  (checkcast "java/lang/String")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "putfield" "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V")
-  (lconst 0)
+  (invoke 4)
+  (invoke 3)
   (return))
 
 (function emit_checkcast (m class)
+  (load-function emit_ref2)
+  (load m)
+  (lconst 192)
+  (load-function cp_class)
+  (load-function method_cf)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
+  (invoke 1)
   (load class)
-  (checkcast "java/lang/String")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "checkcast" "(Ljava/lang/String;)V")
-  (lconst 0)
+  (invoke 2)
+  (invoke 3)
   (return))
 
 (function emit_anewarray (m class)
+  (load-function emit_ref2)
+  (load m)
+  (lconst 189)
+  (load-function cp_class)
+  (load-function method_cf)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
+  (invoke 1)
   (load class)
-  (checkcast "java/lang/String")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "anewarray" "(Ljava/lang/String;)V")
-  (lconst 0)
+  (invoke 2)
+  (invoke 3)
   (return))
 
 (function emit_instanceof (m class)
+  (load-function emit_ref2)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
   (lconst 193)
-  (checkcast "java/lang/Long")
-  (invokevirtual "java/lang/Long" "intValue" "()I")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "u1" "(I)V")
+  (load-function cp_class)
+  (load-function method_cf)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
-  (getfield "com/tailrecursion/larquil/stage0/MethodCode" "cf" "Lcom/tailrecursion/larquil/stage0/ClassFile;")
+  (invoke 1)
   (load class)
-  (checkcast "java/lang/String")
-  (invokevirtual "com/tailrecursion/larquil/stage0/ClassFile" "cpClass" "(Ljava/lang/String;)I")
-  (i2l)
-  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
-  (store idx)
-  (load-function emit_u2)
-  (load m)
-  (load idx)
   (invoke 2)
+  (invoke 3)
   (return))
 
 (function emit_new (m class)
+  (load-function emit_ref2)
+  (load m)
+  (lconst 187)
+  (load-function cp_class)
+  (load-function method_cf)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
+  (invoke 1)
   (load class)
-  (checkcast "java/lang/String")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "newobj" "(Ljava/lang/String;)V")
-  (lconst 0)
+  (invoke 2)
+  (invoke 3)
   (return))
 
 (function emit_invokespecial (m owner name descriptor)
+  (load-function emit_ref2)
+  (load m)
+  (lconst 183)
+  (load-function cp_methodref)
+  (load-function method_cf)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
+  (invoke 1)
   (load owner)
-  (checkcast "java/lang/String")
   (load name)
-  (checkcast "java/lang/String")
   (load descriptor)
-  (checkcast "java/lang/String")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "invokespecial" "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V")
-  (lconst 0)
+  (invoke 4)
+  (invoke 3)
   (return))
 
 (function emit_invokevirtual (m owner name descriptor)
+  (load-function emit_ref2)
+  (load m)
+  (lconst 182)
+  (load-function cp_methodref)
+  (load-function method_cf)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
+  (invoke 1)
   (load owner)
-  (checkcast "java/lang/String")
   (load name)
-  (checkcast "java/lang/String")
   (load descriptor)
-  (checkcast "java/lang/String")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "invokevirtual" "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V")
-  (lconst 0)
+  (invoke 4)
+  (invoke 3)
   (return))
 
 (function emit_invokestatic (m owner name descriptor)
+  (load-function emit_ref2)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
+  (lconst 184)
+  (load-function cp_methodref)
+  (load-function method_cf)
+  (load m)
+  (invoke 1)
   (load owner)
-  (checkcast "java/lang/String")
   (load name)
-  (checkcast "java/lang/String")
   (load descriptor)
-  (checkcast "java/lang/String")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "invokestatic" "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V")
-  (lconst 0)
+  (invoke 4)
+  (invoke 3)
   (return))
 
 (function emit_invokeinterface (m owner name descriptor count)
+  (load-function emit_u1)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
+  (lconst 185)
+  (invoke 2)
+  (pop)
+  (load-function emit_u2)
+  (load m)
+  (load-function cp_interface_methodref)
+  (load-function method_cf)
+  (load m)
+  (invoke 1)
   (load owner)
-  (checkcast "java/lang/String")
   (load name)
-  (checkcast "java/lang/String")
   (load descriptor)
-  (checkcast "java/lang/String")
+  (invoke 4)
+  (invoke 2)
+  (pop)
+  (load-function emit_u1)
+  (load m)
   (load count)
-  (checkcast "java/lang/Long")
-  (invokevirtual "java/lang/Long" "intValue" "()I")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "invokeinterface" "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V")
+  (invoke 2)
+  (pop)
+  (load-function emit_u1)
+  (load m)
+  (lconst 0)
+  (invoke 2)
   (lconst 0)
   (return))
 
 (function emit_branch (m opcode label)
+  (load-function method_branch)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
   (load opcode)
-  (checkcast "java/lang/Long")
-  (invokevirtual "java/lang/Long" "intValue" "()I")
   (load label)
-  (checkcast "java/lang/String")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "branch" "(ILjava/lang/String;)V")
+  (invoke 3)
   (lconst 0)
   (return))
 
 (function emit_label (m label)
+  (load-function method_label)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
   (load label)
-  (checkcast "java/lang/String")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "label" "(Ljava/lang/String;)V")
-  (lconst 0)
-  (return))
-
-(function finish_labels (m)
-  (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "finishLabels" "()V")
+  (invoke 2)
   (lconst 0)
   (return))
 
diff --git a/stage1/instructions.lql b/stage1/instructions.lql
index ec5bcec..a71cb4f 100644
--- a/stage1/instructions.lql
+++ b/stage1/instructions.lql
@@ -256,17 +256,13 @@
   (load state)
   (invoke 1)
   (store left)
+  (load-function method_next_internal)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "nextInternal" "()I")
-  (i2l)
-  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
+  (invoke 1)
   (store n1)
+  (load-function method_next_internal)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "nextInternal" "()I")
-  (i2l)
-  (invokestatic "java/lang/Long" "valueOf" "(J)Ljava/lang/Long;")
+  (invoke 1)
   (store n2)
   (new "java/lang/StringBuilder")
   (dup)
@@ -417,15 +413,16 @@
   (lconst 2)
   (invoke 2)
   (pop)
+  (load-function emit_label)
   (load m)
-  (checkcast "com/tailrecursion/larquil/stage0/MethodCode")
   (load xs)
   (checkcast "java/util/ArrayList")
   (iconst 1)
   (invokevirtual "java/util/ArrayList" "get" "(I)Ljava/lang/Object;")
   (checkcast "com/tailrecursion/larquil/stage0/Symbol")
   (getfield "com/tailrecursion/larquil/stage0/Symbol" "name" "Ljava/lang/String;")
-  (invokevirtual "com/tailrecursion/larquil/stage0/MethodCode" "label" "(Ljava/lang/String;)V")
+  (invoke 2)
+  (pop)
   (lconst 0)
   (return)
   (label try_aconst_null)
diff --git a/test/run.sh b/test/run.sh
index f36a9cb..cc45b29 100755
--- a/test/run.sh
+++ b/test/run.sh
@@ -97,10 +97,6 @@ compile_ok jvm_ops "$ROOT/test/cases/ok/jvm_ops.lql"
 run_loader jvm_ops com.tailrecursion.larquil.stage0.jvm_ops
 expect_output 7
 
-compile_ok stage1_emit "$ROOT/stage1/emit.lql"
-test -f "$OUT/stage1_emit/com/tailrecursion/larquil/stage0/emit__emit_u1.class" || fail "stage1 emit helper class exists"
-ok "stage1 emit class files"
-
 compile_ok stage1_core "$ROOT/stage1/core.lql"
 test -f "$OUT/stage1_core/com/tailrecursion/larquil/stage0/core__lookup.class" || fail "stage1 core helper class exists"
 ok "stage1 core class files"
@@ -111,7 +107,7 @@ ok "stage1 munge class files"
 
 aggregate="$OUT/stage1_compiler_src/compiler.lql"
 mkdir -p "$OUT/stage1_compiler_src"
-cat "$ROOT/stage1/core.lql" "$ROOT/stage1/munge.lql" "$ROOT/stage1/forms.lql" "$ROOT/stage1/reader.lql" "$ROOT/stage1/emit.lql" "$ROOT/stage1/instructions.lql" "$ROOT/stage1/backend.lql" "$ROOT/stage1/compiler.lql" > "$aggregate"
+cat "$ROOT/stage1/core.lql" "$ROOT/stage1/munge.lql" "$ROOT/stage1/forms.lql" "$ROOT/stage1/reader.lql" "$ROOT/stage1/classfile.lql" "$ROOT/stage1/emit.lql" "$ROOT/stage1/instructions.lql" "$ROOT/stage1/backend.lql" "$ROOT/stage1/compiler.lql" > "$aggregate"
 compile_ok stage1_compiler "$aggregate"
 test -f "$OUT/stage1_compiler/com/tailrecursion/larquil/stage0/compiler__is_named_function.class" || fail "stage1 aggregate helper class exists"
 ok "stage1 aggregate class files"