Add Lyng bytecode VM spec draft
This commit is contained in:
parent
b674ee7c18
commit
bc9e557814
200
docs/BytecodeSpec.md
Normal file
200
docs/BytecodeSpec.md
Normal file
@ -0,0 +1,200 @@
|
||||
# Lyng Bytecode VM Spec v0 (Draft)
|
||||
|
||||
This document describes a register-like (3-address) bytecode for Lyng with
|
||||
dynamic slot width (8/16/32-bit slot IDs), a slot-tail argument model, and
|
||||
typed lanes for Obj/Int/Real/Bool. The VM is intended to run as a suspendable
|
||||
interpreter and fall back to the existing AST execution when needed.
|
||||
|
||||
## 1) Frame & Slot Model
|
||||
|
||||
### Frame metadata
|
||||
- localCount: number of local slots for this function (fixed at compile time).
|
||||
- argCount: number of arguments passed at call time.
|
||||
- argBase = localCount.
|
||||
|
||||
### Slot layout
|
||||
slots[0 .. localCount-1] locals
|
||||
slots[localCount .. localCount+argCount-1] arguments
|
||||
|
||||
### Typed lanes
|
||||
- slotType[]: UNKNOWN/OBJ/INT/REAL/BOOL
|
||||
- objSlots[], intSlots[], realSlots[], boolSlots[]
|
||||
- A slot is a logical index; active lane is selected by slotType.
|
||||
|
||||
### Parameter access
|
||||
- param i => slot localCount + i
|
||||
- variadic extra => slot localCount + declaredParamCount + k
|
||||
|
||||
## 2) Slot ID Width
|
||||
|
||||
Per frame, select:
|
||||
- 8-bit if localCount + argCount < 256
|
||||
- 16-bit if < 65536
|
||||
- 32-bit otherwise
|
||||
|
||||
The decoder uses a dedicated loop per width. All slot operands are expanded to
|
||||
Int internally.
|
||||
|
||||
## 3) CALL Semantics (Model A)
|
||||
|
||||
Instruction:
|
||||
CALL_DIRECT fnId, argBase, argCount, dst
|
||||
|
||||
Behavior:
|
||||
- Allocate a callee frame sized localCount + argCount.
|
||||
- Copy caller slots [argBase .. argBase+argCount-1] into callee slots
|
||||
[localCount .. localCount+argCount-1].
|
||||
- Callee returns via RET slot or RET_VOID.
|
||||
- Caller stores return value to dst.
|
||||
|
||||
Other calls:
|
||||
- CALL_VIRTUAL recvSlot, methodId, argBase, argCount, dst
|
||||
- CALL_FALLBACK stmtId, argBase, argCount, dst
|
||||
|
||||
## 4) Binary Encoding Layout
|
||||
|
||||
All instructions are:
|
||||
[opcode:U8] [operands...]
|
||||
|
||||
Operand widths:
|
||||
- slotId: S = 1/2/4 bytes (per frame slot width)
|
||||
- constId: K = 2 bytes (U16), extend to 4 if needed
|
||||
- ip: I = 2 bytes (U16) or 4 bytes (U32) per function size
|
||||
- fnId/methodId/stmtId: F/M/T = 2 bytes (U16) unless extended
|
||||
- argCount: C = 2 bytes (U16), extend to 4 if needed
|
||||
|
||||
Endianness: little-endian for multi-byte operands.
|
||||
|
||||
Common operand patterns:
|
||||
- S: one slot
|
||||
- SS: two slots
|
||||
- SSS: three slots
|
||||
- K S: constId + dst slot
|
||||
- S I: slot + jump target
|
||||
- I: jump target
|
||||
- F S C S: fnId, argBase slot, argCount, dst slot
|
||||
|
||||
## 5) Opcode Table
|
||||
|
||||
Note: Any opcode can be compiled to FALLBACK if not implemented in a VM pass.
|
||||
|
||||
### Data movement
|
||||
- NOP
|
||||
- MOVE_OBJ S -> S
|
||||
- MOVE_INT S -> S
|
||||
- MOVE_REAL S -> S
|
||||
- MOVE_BOOL S -> S
|
||||
- CONST_OBJ K -> S
|
||||
- CONST_INT K -> S
|
||||
- CONST_REAL K -> S
|
||||
- CONST_BOOL K -> S
|
||||
- CONST_NULL -> S
|
||||
|
||||
### Numeric conversions
|
||||
- INT_TO_REAL S -> S
|
||||
- REAL_TO_INT S -> S
|
||||
- BOOL_TO_INT S -> S
|
||||
- INT_TO_BOOL S -> S
|
||||
|
||||
### Arithmetic: INT
|
||||
- ADD_INT S, S -> S
|
||||
- SUB_INT S, S -> S
|
||||
- MUL_INT S, S -> S
|
||||
- DIV_INT S, S -> S
|
||||
- MOD_INT S, S -> S
|
||||
- NEG_INT S -> S
|
||||
- INC_INT S
|
||||
- DEC_INT S
|
||||
|
||||
### Arithmetic: REAL
|
||||
- ADD_REAL S, S -> S
|
||||
- SUB_REAL S, S -> S
|
||||
- MUL_REAL S, S -> S
|
||||
- DIV_REAL S, S -> S
|
||||
- NEG_REAL S -> S
|
||||
|
||||
### Bitwise: INT
|
||||
- AND_INT S, S -> S
|
||||
- OR_INT S, S -> S
|
||||
- XOR_INT S, S -> S
|
||||
- SHL_INT S, S -> S
|
||||
- SHR_INT S, S -> S
|
||||
- USHR_INT S, S -> S
|
||||
- INV_INT S -> S
|
||||
|
||||
### Comparisons (typed)
|
||||
- CMP_EQ_INT S, S -> S
|
||||
- CMP_NEQ_INT S, S -> S
|
||||
- CMP_LT_INT S, S -> S
|
||||
- CMP_LTE_INT S, S -> S
|
||||
- CMP_GT_INT S, S -> S
|
||||
- CMP_GTE_INT S, S -> S
|
||||
- CMP_EQ_REAL S, S -> S
|
||||
- CMP_NEQ_REAL S, S -> S
|
||||
- CMP_LT_REAL S, S -> S
|
||||
- CMP_LTE_REAL S, S -> S
|
||||
- CMP_GT_REAL S, S -> S
|
||||
- CMP_GTE_REAL S, S -> S
|
||||
- CMP_EQ_BOOL S, S -> S
|
||||
- CMP_NEQ_BOOL S, S -> S
|
||||
|
||||
### Mixed numeric comparisons
|
||||
- CMP_EQ_INT_REAL S, S -> S
|
||||
- CMP_EQ_REAL_INT S, S -> S
|
||||
- CMP_LT_INT_REAL S, S -> S
|
||||
- CMP_LT_REAL_INT S, S -> S
|
||||
- CMP_LTE_INT_REAL S, S -> S
|
||||
- CMP_LTE_REAL_INT S, S -> S
|
||||
- CMP_GT_INT_REAL S, S -> S
|
||||
- CMP_GT_REAL_INT S, S -> S
|
||||
- CMP_GTE_INT_REAL S, S -> S
|
||||
- CMP_GTE_REAL_INT S, S -> S
|
||||
|
||||
### Boolean ops
|
||||
- NOT_BOOL S -> S
|
||||
- AND_BOOL S, S -> S
|
||||
- OR_BOOL S, S -> S
|
||||
|
||||
### Control flow
|
||||
- JMP I
|
||||
- JMP_IF_TRUE S, I
|
||||
- JMP_IF_FALSE S, I
|
||||
- RET S
|
||||
- RET_VOID
|
||||
|
||||
### Calls
|
||||
- CALL_DIRECT F, S, C, S
|
||||
- CALL_VIRTUAL S, M, S, C, S
|
||||
- CALL_FALLBACK T, S, C, S
|
||||
|
||||
### Object access (optional, later)
|
||||
- GET_FIELD S, M -> S
|
||||
- SET_FIELD S, M, S
|
||||
- GET_INDEX S, S -> S
|
||||
- SET_INDEX S, S, S
|
||||
|
||||
### Fallback
|
||||
- EVAL_FALLBACK T -> S
|
||||
|
||||
## 6) Function Header (binary container)
|
||||
|
||||
Suggested layout for a bytecode function blob:
|
||||
- magic: U32 ("LYBC")
|
||||
- version: U16 (0x0001)
|
||||
- slotWidth: U8 (1,2,4)
|
||||
- ipWidth: U8 (2,4)
|
||||
- constIdWidth: U8 (2,4)
|
||||
- localCount: U32
|
||||
- codeSize: U32 (bytes)
|
||||
- constCount: U32
|
||||
- constPool: [const entries...]
|
||||
- code: [bytecode...]
|
||||
|
||||
Const pool entries are encoded as type-tagged values (Obj/Int/Real/Bool/String)
|
||||
in a simple tagged format. This is intentionally unspecified in v0.
|
||||
|
||||
## 7) Notes
|
||||
|
||||
- Mixed-mode is allowed: compiler can emit FALLBACK ops for unsupported nodes.
|
||||
- The VM must be suspendable; on suspension, store ip + minimal operand state.
|
||||
- Source mapping uses a separate ip->Pos table, not part of core bytecode.
|
||||
Loading…
x
Reference in New Issue
Block a user