.stflb bytecode by stoffel-vm-types.
Architecture Overview
The VM uses two related instruction forms:| Form | Purpose |
|---|---|
Instruction | Symbolic representation with labels, function names, and embedded immediate Values. Used by compiler output and direct VM construction. |
ResolvedInstruction | Execution-oriented representation with label targets, constants, and call targets resolved to numeric indices. |
CALL("name") becomes a numeric call-target index plus a call-target name table.
The runtime then lowers resolved instructions into packed runtime instructions for dispatch. The packed runtime opcode mapping is an internal optimization and is not the same thing as the serialized opcode values shown below.
Registers
Bytecode register operands are absolute frame indices. The default layout uses register16 as the secret-register boundary:
| Range | Default bank |
|---|---|
r0..r15 | clear registers |
r16.. | secret registers |
r0is the return register.- The secret boundary is a layout convention, not a hard 32-register maximum.
- Each
VMFunctionhas a frame register count. Registration normalizes the count so it is large enough for parameters, the return register, and every referenced register. - The register file stores clear and secret banks separately even though bytecode operands are absolute indices.
- Moving clear values into secret registers creates or carries share values. Moving secret values back to clear registers becomes a reveal/open operation.
- Pending reveals are stored as register-slot state until the async MPC operation completes.
Frame memory
Each activation frame contains:- function name and local variable map;
- register file;
- captured upvalues;
- a volatile argument stack for
PUSHARG,LD, and calls; - a dedicated spill vector for
STS/LDS; - a compare flag;
- an instruction pointer;
- optional closure metadata.
LD reads from the current frame’s argument stack. Offset 0 resolves to the top argument; negative offsets read below the top.
STS and LDS do not use that argument stack. They access a stable per-frame spill area used by register allocation, so spilled values survive between call argument pushes without being confused with function-call arguments.
Value types
The VM value enum includes:| Variant family | Runtime shape |
|---|---|
| Signed integers | I64, I32, I16, I8 |
| Unsigned integers | U64, U32, U16, U8 |
| Other scalars | Float(F64), Bool, String, Unit |
| VM-managed references | Object(ObjectRef), Array(ArrayRef), Foreign(ForeignObjectRef), Closure(...) |
| Shares | Share(ShareType, ShareData) |
.stflb files.
Share type metadata is shape-oriented:
- secret int: 64 bits;
- secret bool: one-bit secret int;
- fixed point: 64 total bits, 16 fractional bits.
Instruction set
Loading and movement
| Instruction | Operands | Effect |
|---|---|---|
NOP | — | No operation. |
LD | dest, stack_offset | Load from current frame’s argument stack. |
LDI | dest, value | Load an immediate value; serialized bytecode stores a constant index. |
MOV | dest, src | Move/copy a register value, including clear/secret bank transitions. |
PUSHARG | src | Push a register value onto the call argument stack. |
STS | slot, src | Store a raw value into the frame spill area. |
LDS | dest, slot | Load a raw value from the frame spill area. |
Arithmetic and bitwise operations
Arithmetic instructions usedest, left, right operands:
| Instruction | Meaning |
|---|---|
ADD | dest = left + right |
SUB | dest = left - right |
MUL | dest = left * right |
DIV | dest = left / right |
MOD | dest = left % right |
| Instruction | Meaning |
|---|---|
AND | dest = left & right |
OR | dest = left | right |
XOR | dest = left ^ right |
NOT | dest = !src / bitwise not depending on value type |
SHL | dest = value << amount_register |
SHR | dest = value >> amount_register |
SHL and SHR take the shift amount from a register, not an immediate literal operand.
Comparisons and jumps
CMP left, right sets a typed compare flag:
LessEqualGreater
| Instruction | Jumps when |
|---|---|
JMPEQ | comparison was equal |
JMPNEQ | comparison was not equal |
JMPLT | comparison was less than |
JMPGT | comparison was greater than |
JMP jumps unconditionally to a label in symbolic form or instruction index in resolved form.
Calls and returns
| Instruction | Purpose |
|---|---|
CALL name | Call a VM or foreign function. Arguments must have been pushed with PUSHARG. |
RET src | Return a register value to the caller. |
r0 as the return register for fallthrough-style completion.
Serialized opcode values
The opcode values used by serialized bytecode are:| Hex | Instruction |
|---|---|
0x00 | LD |
0x01 | LDI |
0x02 | MOV |
0x03 | ADD |
0x04 | SUB |
0x05 | MUL |
0x06 | DIV |
0x07 | MOD |
0x08 | AND |
0x09 | OR |
0x0A | XOR |
0x0B | NOT |
0x0C | SHL |
0x0D | SHR |
0x0E | JMP |
0x0F | JMPEQ |
0x10 | JMPNEQ |
0x11 | CALL |
0x12 | RET |
0x13 | PUSHARG |
0x14 | CMP |
0x15 | JMPLT |
0x16 | JMPGT |
0x17 | NOP |
0x18 | LDS |
0x19 | STS |
Bytecode format
Compiled bytecode is stored in.stflb files. The format is defined by stoffel-vm-types::compiled_binary.
Current format facts:
- magic bytes:
STFL; - format version:
9; - version 9 added
LDS/STSspill-slot instructions; - generic collection guardrail: 1,000,000 items;
- per-function instruction guardrail: 8,000,000 instructions;
- string/blob guardrail: 16 MiB.
Constants
The constant pool supports scalar constants:Unit- signed and unsigned integer values
FloatBoolString
Function records
A compiled function stores:- name;
- parameters;
- parameter types;
- return type;
- upvalues;
- optional parent function name;
- frame register count;
- labels;
- instructions.
Client and MPC manifest
The bytecode manifest carries MPC-facing metadata used by the CLI and SDK:- selected MPC backend, such as HoneyBadger or AVSS;
- selected curve/field configuration;
- client input/output schemas by client slot;
- static preprocessing demand estimate.
dynamic flag for cases where runtime demand may exceed the static estimate.