Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
501b438
Add FAST_CALL instruction
matthew-mojira Oct 6, 2025
9385870
Update tag for fast_call
matthew-mojira Oct 6, 2025
ca553b9
Separate more fast call behavior
matthew-mojira Oct 8, 2025
93347ff
Add CallProperty to distinguish between tail call and fast call
matthew-mojira Oct 14, 2025
9a7d2ef
Add stubs/initialization for fast call entries and no-op FAST_CALL in…
matthew-mojira Jan 5, 2026
a3e2ab6
Clean up unused dispatch function and specify goals
matthew-mojira Jan 5, 2026
f922f4f
Work on SPC accepting fast mode and emitting dispatch sequence
matthew-mojira Jan 5, 2026
f736bd2
macro dispatch, add fast_target_code correctly, better stub caller di…
matthew-mojira Jan 14, 2026
6056e47
Fix vsp in fast spc
matthew-mojira Jan 15, 2026
4e7ea0e
Replace CALL with FAST_CALL when function is exported with "fast:" pr…
matthew-mojira Jan 15, 2026
f6bb78d
AOT compile fast functions declared in export name
matthew-mojira Jan 21, 2026
bcc3dcd
Add fast prologue/epilogue stubs
matthew-mojira Jan 21, 2026
50c5bcf
Add small frame in fast call to save vfp (for local variables)
matthew-mojira Jan 22, 2026
599e42c
Add test files/programs
matthew-mojira Jan 23, 2026
f6c8e0c
Add logic for specialized FAST_CALL bytecodes
matthew-mojira Jan 23, 2026
7a88431
Add more instructions
matthew-mojira Mar 11, 2026
9fd6864
Remove use of fast frame
matthew-mojira Mar 18, 2026
03b6ccd
Add FAST_CALL 0-47 for each unused bytecode, and minor merge fixes
matthew-mojira Apr 1, 2026
6cd1466
Patch the dispatch table with fast-compiled functions (and use them) …
matthew-mojira Apr 1, 2026
7e7013b
Cleaned up some stuff
matthew-mojira Apr 2, 2026
b8a1636
Remove unused stubs and deps
matthew-mojira Apr 2, 2026
b48b03a
Build fast SPC exec env at the same time as other exec envs, remove dup
matthew-mojira Apr 2, 2026
f11a114
save/restore caller IVars in SPC and across frame reconstruction
matthew-mojira Apr 2, 2026
4643990
Complete stack reconstruction around fast compilation
matthew-mojira Apr 3, 2026
16ab7ba
Remove FAST_CALL47 and opcode mapped to 0xFF
matthew-mojira Apr 3, 2026
66c34c7
Remove more FAST_CALLs contradicting stack switching
matthew-mojira Apr 3, 2026
cd93c2b
Move fast_target_code and fast_call_idx (conflict in internal offset!…
matthew-mojira Apr 3, 2026
8b0249a
fixup! save/restore caller IVars in SPC and across frame reconstruction
matthew-mojira Apr 5, 2026
e8d0b8e
fixup! Add CallProperty to distinguish between tail call and fast call
matthew-mojira Apr 5, 2026
b85fcd1
Add options for fast functions
matthew-mojira Apr 5, 2026
7d68a0d
Fast call tests
matthew-mojira Apr 5, 2026
b62026c
Fix regular inlining
matthew-mojira Apr 5, 2026
cb75fc6
Add .wat from tests and more fastcall tests
matthew-mojira Apr 6, 2026
fed74c1
Fix multi_return test (div incorrect)
matthew-mojira Apr 8, 2026
227ef84
Add stackframe test
matthew-mojira Apr 8, 2026
6e79fee
Save interpreter r_ip into the frame (to protect against div)
matthew-mojira Apr 8, 2026
545db5e
Fix test expectation
matthew-mojira Apr 8, 2026
b913d52
Validate interpreter's pc in a fast function's outcall
matthew-mojira Apr 8, 2026
c2d4d5f
Add more tests
matthew-mojira Apr 9, 2026
ad9ab8d
Update some register stuff
matthew-mojira Apr 9, 2026
b540398
Claude's junk
matthew-mojira Apr 15, 2026
80c1a61
Revert "Claude's junk"
matthew-mojira Apr 15, 2026
a490e0b
Streamline compiler to help fix bug
matthew-mojira Apr 17, 2026
6ec6747
Fix saving of vfp
matthew-mojira Apr 20, 2026
2b5bc9e
More vfp fix progress
matthew-mojira Apr 20, 2026
55f3e97
Fix bug
matthew-mojira Apr 20, 2026
3bcd8b1
Fix test expectation
matthew-mojira Apr 20, 2026
3629afd
Remove too early of Instance.functions
matthew-mojira Apr 20, 2026
3d1733e
Fix non-fast reconstruction
matthew-mojira Apr 20, 2026
73f8c2b
Remove unnecessary else if block
matthew-mojira Apr 20, 2026
e5b1bb1
Streamline code to detect fast handlers in hardware traps
matthew-mojira Apr 20, 2026
990221d
Remove `int` directory
matthew-mojira Apr 21, 2026
b9e8feb
Refactor SPC
matthew-mojira Apr 21, 2026
582aec9
Revert "Add CallProperty to distinguish between tail call and fast call"
matthew-mojira Apr 21, 2026
9f1dad5
Refactor and clean up code
matthew-mojira Apr 21, 2026
e2b1009
Remove printing fast function
matthew-mojira Apr 21, 2026
39f5519
Remove (lazy) fastCompile function
matthew-mojira Apr 21, 2026
37c3f84
Add guards around FastIntTuning.useFastFunctions
matthew-mojira Apr 21, 2026
28cd098
Deduplicate Mmap.reserve
matthew-mojira Apr 21, 2026
351ecbb
Remove FAST_SPC_EXEC_ENV
matthew-mojira Apr 21, 2026
c2b27da
Rename _reserve to reserve_
matthew-mojira Apr 21, 2026
cd863dc
Add more tests from CLAUDE
matthew-mojira Apr 21, 2026
73251ee
Always reconstruct frames across runtime calls in fast handler
matthew-mojira Apr 21, 2026
eac78ce
Streamline SPC register saving (should just be sent to MacroAssembler…
matthew-mojira Apr 22, 2026
004c04e
Revert "Streamline SPC register saving (should just be sent to MacroA…
matthew-mojira Apr 22, 2026
9fa6781
Add wave.new_func tests to fastcall
matthew-mojira Apr 22, 2026
9e3df1d
Optimize replaceCall
matthew-mojira Apr 22, 2026
fb42f99
Print out patches to dispatch table
matthew-mojira Apr 22, 2026
bf07a5d
Eagely allocate fast handler slots
matthew-mojira Apr 22, 2026
09021c6
Save r_stp during reconstruction
matthew-mojira Apr 23, 2026
33b9ebc
Add even more tests
matthew-mojira Apr 28, 2026
bdbc235
Assign fast_call_idx during parsing
matthew-mojira Apr 28, 2026
2ccc1a4
Add fixes PR to master
matthew-mojira Apr 28, 2026
098aaa7
Spill registers in visitCallIndirect in fast mode (Why?)
matthew-mojira Apr 28, 2026
a842fdd
Streamline save/restore of interpreter registers
matthew-mojira Apr 28, 2026
6648726
Fast compile modules on JIT compiler tiers
matthew-mojira Apr 29, 2026
21f268a
Do not inline non-fast functions when fast handlers are in use
matthew-mojira Apr 29, 2026
1c54b72
Add (fast) to fast-compiled compiler traces
matthew-mojira Apr 29, 2026
e7c9a79
Add tests that use new_func
matthew-mojira Jun 3, 2026
8f1403b
Don't restore instance and mem0base after stack reconstruction
matthew-mojira Jun 4, 2026
3bf3afe
Change registers to only be restored if there is an outcall
matthew-mojira Jun 15, 2026
cc982c7
Merge remote-tracking branch 'origin/master' into fast-handlers
matthew-mojira Jun 17, 2026
74ac5c3
Merge remote-tracking branch 'origin/master' into fast-handlers
matthew-mojira Jun 17, 2026
637d2c5
Move restoreDispatchTableReg and computePc to MacroAssembler
matthew-mojira Jun 17, 2026
3171e2d
Update comments
matthew-mojira Jun 22, 2026
1f65ca5
Restore save of registers
matthew-mojira Jun 22, 2026
7b56a20
Reset fast_has_outcall in gen0
matthew-mojira Jun 22, 2026
ab6ccbb
Remove swp file
matthew-mojira Jun 22, 2026
f067b51
Merge remote-tracking branch 'origin/master' into fast-handlers
matthew-mojira Jul 3, 2026
ded4546
Clean up repo
matthew-mojira Jul 3, 2026
87fba3d
Fail upon validating FAST_CALL instructions
matthew-mojira Jul 22, 2026
4c2953f
Only allow interpreter code region to be writable during module load …
matthew-mojira Jul 25, 2026
49f3c6e
Throw error on duplicate fast exports, use interpreter fallback for c…
matthew-mojira Jul 27, 2026
fb43a64
Merge branch 'titzer:master' into fast-handlers
matthew-mojira Jul 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/engine/BinParser.v3
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,20 @@ class BinParser(extensions: Extension.set, limits: Limits, err: ErrorGen, filena
}
var decl = readExportWithoutName();
module.exports.put(name, decl);
// assign fast functions
if (FastIntTuning.useFastFunctions && Strings.startsWith(name, "fast:") && FuncDecl.?(decl)) {
def fdecl = FuncDecl.!(decl);
def fast_funcs = module.fast_funcs;
if (fdecl.fast_call_idx >= 0) {
err.rel(decoder, pt).DuplicateFastExport(fdecl.func_index);
} else if (fast_funcs.length >= Opcodes.FAST_CALL_OPCODES) {
// No fast-call slot available; fall back to a regular call for this function.
if (Trace.validation) Trace.OUT.put1(" dropping fast: export, no FAST_CALL slots remain (max %d)\n", Opcodes.FAST_CALL_OPCODES);
} else {
fdecl.fast_call_idx = fast_funcs.length;
fast_funcs.put(fdecl);
}
}
}
def readExportWithoutName() -> Decl {
var pt = decoder.pos;
Expand Down
42 changes: 42 additions & 0 deletions src/engine/BytecodeIterator.v3
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,48 @@ class BytecodeIterator {
RESUME_THROW => v.visit_RESUME_THROW(read_CONT(), read_TAG(), read_HANDLERS());
RESUME_THROW_REF => v.visit_RESUME_THROW_REF(read_CONT(), read_HANDLERS());
SWITCH => v.visit_SWITCH(read_CONT(), read_TAG());

// replacing CALL with FAST_CALL does not touch the operand so that the original function can still be recovered
FAST_CALL0 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL1 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL2 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL3 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL4 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL5 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL6 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL7 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL8 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL9 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL10 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL11 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL12 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL13 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL14 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL15 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL16 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL17 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL18 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL19 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL20 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL21 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL22 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL23 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL24 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL25 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL26 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL27 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL28 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL29 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL30 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL31 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL32 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL33 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL34 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL35 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL36 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL37 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL38 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
FAST_CALL39 => v.visit_FAST_CALL(Opcodes.fastCallToIndex(opcode), read_FUNC());
}
}
def trace(out: StringBuilder, module: Module, tracer: InstrTracer) {
Expand Down
6 changes: 6 additions & 0 deletions src/engine/CodeValidator.v3
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,12 @@ class CodeValidator(extensions: Extension.set, limits: Limits, module: Module, e
var func = parser.readFuncRef();
if (func == null) return;
checkSignature(func.sig);

// fast call: if function is exported with fast name, replace the bytecode with FAST_CALL
if (FastIntTuning.useFastFunctions && func.fast_call_idx >= 0) {
if (Trace.validation) Trace.OUT.put1(" replacing with FAST_CALL%d\n", func.fast_call_idx);
this.func.replaceCall(opcode_pos, func.fast_call_idx);
}
}
CALL_INDIRECT => {
var sig = parser.readSigRef();
Expand Down
10 changes: 10 additions & 0 deletions src/engine/Module.v3
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Module(filename: string) {
def exports = Vector<(string, Decl)>.new();
def elems = Vector<ElemDecl>.new();
def data = Vector<DataDecl>.new();
def fast_funcs = Vector<FuncDecl>.new();
def custom_sections = Vector<CustomSection>.new();
var probes: Array<Array<Probe>>;
var dyn_probes: Vector<(int, int, Probe)>;
Expand Down Expand Up @@ -143,6 +144,8 @@ class FuncDecl(sig_index: int) extends Decl {
var target_code: TargetCode;
var tierup_trigger: int = int.max;
var handlers = FuncHandlerInfo.new();
var fast_target_code: TargetCode;
var fast_call_idx: int = -1;

def render(names: NameSection, buf: StringBuilder) -> StringBuilder {
var name = if (names != null, names.getFuncName(func_index));
Expand All @@ -154,6 +157,7 @@ class FuncDecl(sig_index: int) extends Decl {
var tc: TargetCode;
var tr: TargetCode;
target_code = tc; // reset target code as well
fast_target_code = tc;
sidetable = Sidetables.NO_SIDETABLE;
cbd_sidetable = null;
}
Expand All @@ -168,6 +172,11 @@ class FuncDecl(sig_index: int) extends Decl {
if (cur_bytecode == orig_bytecode) return;
cur_bytecode[pc] = orig_bytecode[pc];
}
def replaceCall(pc: int, idx: int) {
// copy bytecode for modification
if (cur_bytecode == orig_bytecode) orig_bytecode = Arrays.dup(orig_bytecode);
cur_bytecode[pc] = byte.!(Opcodes.indexToFastCall(idx).code);
}
def reset() -> this {
if (cur_bytecode == orig_bytecode) return;
ArrayUtil.copyInto(cur_bytecode, 0, orig_bytecode, 0, orig_bytecode.length);
Expand All @@ -183,6 +192,7 @@ class FuncDecl(sig_index: int) extends Decl {
n.sidetable = this.sidetable;
n.num_locals = this.num_locals;
n.target_code = this.target_code;
n.fast_target_code = this.fast_target_code;
return n;
}
def findExHandler(instance: Instance, tag: Tag, throw_pc: int) -> ExHandler {
Expand Down
145 changes: 145 additions & 0 deletions src/engine/Opcodes.v3
Original file line number Diff line number Diff line change
Expand Up @@ -609,8 +609,51 @@ enum Opcode(prefix: u8, code: u16, mnemonic: string, imms: Array<ImmKind>, sig:
RESUME_THROW (0x00, 0xE4, "resume_throw", imm.CONT_TAG_HANDLE, null),
RESUME_THROW_REF (0x00, 0xE5, "resume_throw_ref", imm.CONT_HANDLE, null),
SWITCH (0x00, 0xE6, "switch", imm.CONT_TAG, null)

// fast call instructions
FAST_CALL0 (0x00, 0xC5, "fast_call0", imm.FUNC, null),
FAST_CALL1 (0x00, 0xC6, "fast_call1", imm.FUNC, null),
FAST_CALL2 (0x00, 0xC7, "fast_call2", imm.FUNC, null),
FAST_CALL3 (0x00, 0xC8, "fast_call3", imm.FUNC, null),
FAST_CALL4 (0x00, 0xC9, "fast_call4", imm.FUNC, null),
FAST_CALL5 (0x00, 0xCA, "fast_call5", imm.FUNC, null),
FAST_CALL6 (0x00, 0xCB, "fast_call6", imm.FUNC, null),
FAST_CALL7 (0x00, 0xCC, "fast_call7", imm.FUNC, null),
FAST_CALL8 (0x00, 0xCD, "fast_call8", imm.FUNC, null),
FAST_CALL9 (0x00, 0xCE, "fast_call9", imm.FUNC, null),
FAST_CALL10 (0x00, 0xCF, "fast_call10", imm.FUNC, null),
FAST_CALL11 (0x00, 0xD7, "fast_call11", imm.FUNC, null),
FAST_CALL12 (0x00, 0xD8, "fast_call12", imm.FUNC, null),
FAST_CALL13 (0x00, 0xD9, "fast_call13", imm.FUNC, null),
FAST_CALL14 (0x00, 0xDA, "fast_call14", imm.FUNC, null),
FAST_CALL15 (0x00, 0xDB, "fast_call15", imm.FUNC, null),
FAST_CALL16 (0x00, 0xDC, "fast_call16", imm.FUNC, null),
FAST_CALL17 (0x00, 0xDD, "fast_call17", imm.FUNC, null),
FAST_CALL18 (0x00, 0xDE, "fast_call18", imm.FUNC, null),
FAST_CALL19 (0x00, 0xDF, "fast_call19", imm.FUNC, null),
FAST_CALL20 (0x00, 0xE7, "fast_call20", imm.FUNC, null),
FAST_CALL21 (0x00, 0xE8, "fast_call21", imm.FUNC, null),
FAST_CALL22 (0x00, 0xE9, "fast_call22", imm.FUNC, null),
FAST_CALL23 (0x00, 0xEA, "fast_call23", imm.FUNC, null),
FAST_CALL24 (0x00, 0xEB, "fast_call24", imm.FUNC, null),
FAST_CALL25 (0x00, 0xEC, "fast_call25", imm.FUNC, null),
FAST_CALL26 (0x00, 0xED, "fast_call26", imm.FUNC, null),
FAST_CALL27 (0x00, 0xEE, "fast_call27", imm.FUNC, null),
FAST_CALL28 (0x00, 0xEF, "fast_call28", imm.FUNC, null),
FAST_CALL29 (0x00, 0xF2, "fast_call29", imm.FUNC, null),
FAST_CALL30 (0x00, 0xF3, "fast_call30", imm.FUNC, null),
FAST_CALL31 (0x00, 0xF4, "fast_call31", imm.FUNC, null),
FAST_CALL32 (0x00, 0xF5, "fast_call32", imm.FUNC, null),
FAST_CALL33 (0x00, 0xF6, "fast_call33", imm.FUNC, null),
FAST_CALL34 (0x00, 0xF7, "fast_call34", imm.FUNC, null),
FAST_CALL35 (0x00, 0xF8, "fast_call35", imm.FUNC, null),
FAST_CALL36 (0x00, 0xF9, "fast_call36", imm.FUNC, null),
FAST_CALL37 (0x00, 0xFA, "fast_call37", imm.FUNC, null),
FAST_CALL38 (0x00, 0x17, "fast_call38", imm.FUNC, null),
FAST_CALL39 (0x00, 0x27, "fast_call39", imm.FUNC, null),
}


// Enumeration of the different kinds of immediates to opcodes.
enum ImmKind {
ARRAY_TYPE_INDEX, // ARRAYT
Expand Down Expand Up @@ -798,9 +841,16 @@ component Opcodes {
def code_pages = [page_FB, page_FC, page_FD, page_FE];
def var longestName: int;
def var num_subpages: int;
def FAST_CALL_OPCODES = 40;
def var fast_calls: Array<Opcode>;
private var nameMap: HashMap<string, Opcode>;

new() {

fast_calls = Array.new(FAST_CALL_OPCODES);
for (i < FAST_CALL_OPCODES) {
fast_calls[i] = indexToFastCall(i);
}
for (op in Opcode) {
if (op == Opcode.INVALID) continue;
init(op);
Expand All @@ -809,6 +859,7 @@ component Opcodes {
attributes[InternalOpcode.PROBE.code] = OpcodeAttribute.INTERNAL | OpcodeAttribute.PROBE;
attributes[InternalOpcode.WHAMM_PROBE.code] = OpcodeAttribute.INTERNAL | OpcodeAttribute.PROBE;
attributes[InternalOpcode.BREAK_PROBE.code] = OpcodeAttribute.INTERNAL | OpcodeAttribute.PROBE;
for (op in fast_calls) attributes[op.tag] = OpcodeAttribute.INTERNAL;

for (op in [Opcode.END, Opcode.I32_CONST, Opcode.I64_CONST, Opcode.F32_CONST, Opcode.F64_CONST, Opcode.GLOBAL_GET,
Opcode.REF_NULL, Opcode.REF_FUNC, Opcode.STRUCT_NEW, Opcode.STRUCT_NEW_DEFAULT,
Expand Down Expand Up @@ -1121,6 +1172,100 @@ component Opcodes {
}
}
}
def indexToFastCall(index: int) -> Opcode {
var op: Opcode;
match (index) {
0 => op = Opcode.FAST_CALL0;
1 => op = Opcode.FAST_CALL1;
2 => op = Opcode.FAST_CALL2;
3 => op = Opcode.FAST_CALL3;
4 => op = Opcode.FAST_CALL4;
5 => op = Opcode.FAST_CALL5;
6 => op = Opcode.FAST_CALL6;
7 => op = Opcode.FAST_CALL7;
8 => op = Opcode.FAST_CALL8;
9 => op = Opcode.FAST_CALL9;
10 => op = Opcode.FAST_CALL10;
11 => op = Opcode.FAST_CALL11;
12 => op = Opcode.FAST_CALL12;
13 => op = Opcode.FAST_CALL13;
14 => op = Opcode.FAST_CALL14;
15 => op = Opcode.FAST_CALL15;
16 => op = Opcode.FAST_CALL16;
17 => op = Opcode.FAST_CALL17;
18 => op = Opcode.FAST_CALL18;
19 => op = Opcode.FAST_CALL19;
20 => op = Opcode.FAST_CALL20;
21 => op = Opcode.FAST_CALL21;
22 => op = Opcode.FAST_CALL22;
23 => op = Opcode.FAST_CALL23;
24 => op = Opcode.FAST_CALL24;
25 => op = Opcode.FAST_CALL25;
26 => op = Opcode.FAST_CALL26;
27 => op = Opcode.FAST_CALL27;
28 => op = Opcode.FAST_CALL28;
29 => op = Opcode.FAST_CALL29;
30 => op = Opcode.FAST_CALL30;
31 => op = Opcode.FAST_CALL31;
32 => op = Opcode.FAST_CALL32;
33 => op = Opcode.FAST_CALL33;
34 => op = Opcode.FAST_CALL34;
35 => op = Opcode.FAST_CALL35;
36 => op = Opcode.FAST_CALL36;
37 => op = Opcode.FAST_CALL37;
38 => op = Opcode.FAST_CALL38;
39 => op = Opcode.FAST_CALL39;
_ => System.error("indexToFastCall", "out of range");
}
return op;
}
def fastCallToIndex(op: Opcode) -> int {
var idx: int;
match (op) {
FAST_CALL0 => idx = 0;
FAST_CALL1 => idx = 1;
FAST_CALL2 => idx = 2;
FAST_CALL3 => idx = 3;
FAST_CALL4 => idx = 4;
FAST_CALL5 => idx = 5;
FAST_CALL6 => idx = 6;
FAST_CALL7 => idx = 7;
FAST_CALL8 => idx = 8;
FAST_CALL9 => idx = 9;
FAST_CALL10 => idx = 10;
FAST_CALL11 => idx = 11;
FAST_CALL12 => idx = 12;
FAST_CALL13 => idx = 13;
FAST_CALL14 => idx = 14;
FAST_CALL15 => idx = 15;
FAST_CALL16 => idx = 16;
FAST_CALL17 => idx = 17;
FAST_CALL18 => idx = 18;
FAST_CALL19 => idx = 19;
FAST_CALL20 => idx = 20;
FAST_CALL21 => idx = 21;
FAST_CALL22 => idx = 22;
FAST_CALL23 => idx = 23;
FAST_CALL24 => idx = 24;
FAST_CALL25 => idx = 25;
FAST_CALL26 => idx = 26;
FAST_CALL27 => idx = 27;
FAST_CALL28 => idx = 28;
FAST_CALL29 => idx = 29;
FAST_CALL30 => idx = 30;
FAST_CALL31 => idx = 31;
FAST_CALL32 => idx = 32;
FAST_CALL33 => idx = 33;
FAST_CALL34 => idx = 34;
FAST_CALL35 => idx = 35;
FAST_CALL36 => idx = 36;
FAST_CALL37 => idx = 37;
FAST_CALL38 => idx = 38;
FAST_CALL39 => idx = 39;
_ => System.error("fastCallToIndex", "not a FAST_CALL instruction");
}
return idx;
}
}

// Renders instructions as text.
Expand Down
Loading
Loading