#[repr(u8)]pub enum Opcode {
Show 31 variants
Halt = 0,
LoadConst = 1,
Move = 2,
LoadImm = 3,
Add = 16,
Sub = 17,
Mul = 18,
Div = 19,
Mod = 20,
Neg = 21,
Eq = 24,
Lt = 25,
Le = 26,
Jump = 32,
Branch = 33,
Call = 48,
Return = 49,
CallNative = 50,
Spawn = 64,
Yield = 65,
Sleep = 66,
Exit = 67,
SelfPid = 68,
Send = 80,
Receive = 81,
ReceiveTimeout = 82,
ReceiveMatch = 83,
ReceiveMatchImm = 84,
Ask = 85,
Trap = 96,
Nop = 97,
}Expand description
A single Byteflow opcode.
Numeric values are part of the stable on-disk ABI (byteflow-bytecode
module format, see super::chunk::MAGIC) — never renumber an existing
variant, only append.
Variants§
Halt = 0
Stop the current Flow’s VM loop. Terminal state.
LoadConst = 1
LoadConst ra, kb → r[a] = constants[b]
Move = 2
Move ra, rb → r[a] = r[b]
LoadImm = 3
LoadImm ra, imm → r[a] = imm as i64 (fast path, skips const pool)
Add = 16
Sub = 17
Mul = 18
Div = 19
Mod = 20
Neg = 21
Eq = 24
Lt = 25
Le = 26
Jump = 32
Jump imm → unconditional relative jump (imm = signed offset in
instructions from the next pc).
Branch = 33
Branch ra, imm → jump by imm iff r[a] is falsy (Bool(false),
Unit, or Int(0)). This is the only conditional branch; if/else and
loops both lower to Branch + Jump, keeping the interpreter’s branch
predictor state small.
Call = 48
Call ra, fb, nc → call function fb with nc arguments taken from
r[a..a+nc], result written back into r[a].
Return = 49
Return ra → return r[a] to the caller frame (or complete the
Flow if this is the outermost frame).
CallNative = 50
CallNative ra, fb, nc → like Call but fb indexes the native
function table instead of the bytecode function table.
Spawn = 64
Spawn ra, fb, nc → create a new virtual Flow starting at
function fb, passing nc arguments taken from r[a+1..a+1+nc]
(deliberately not overlapping r[a] itself, which is where the
scheduler writes a Cap to the child once created — FlowCap;
see crate::VmResult::Spawn).
Yield = 65
Yield → cooperative yield. Control returns to the scheduler, the
Flow is re-enqueued as Ready and may resume on any worker.
Sleep = 66
Sleep ra → suspend until r[a] (interpreted as milliseconds,
Value::Int) has elapsed. Registered on the timer wheel.
Exit = 67
Exit ra → terminate the Flow, r[a] is delivered to .join().
SelfPid = 68
SelfPid ra → r[a] = a self Cap (SEND|ASK) for this flow.
(Opcode name kept for ABI; the value is Value::Cap, not Pid.)
The VM does not store its own id (it has no scheduler state); this
is a scheduler effect, same class as Spawn/Receive.
Send = 80
Send ra, rb → Atomic Hop: deliver r[b] (Message) to the Cap in
r[a]. Never blocks (mailboxes are unbounded by default).
VM requires Cap + Message; worker resolves Cap (SEND), stamps sender
reply_cap, then pushes to the resolved mailbox.
Receive = 81
Receive ra → pop the next message into r[a]; if the mailbox is
empty, suspends the Flow in Waiting state until a message
arrives.
ReceiveTimeout = 82
ReceiveTimeout ra, rb → like Receive but gives up after r[b]
milliseconds, writing Value::Unit into r[a] on timeout.
ReceiveMatch = 83
ReceiveMatch ra, rb → Atomic Hop selective receive: block until
a crate::Value::Message with tag == r[b] (as u16) is available.
Non-matching hops stay in the mailbox in FIFO order (skip, don’t drop).
ReceiveMatchImm = 84
ReceiveMatchImm ra, imm → like ReceiveMatch with an immediate tag
(imm must fit in u16).
Ask = 85
Ask ra, rb, rc → atomic request/reply hop.
- Validate
r[b]as Cap andr[c]as Message (VM). - Scheduler resolves Cap (ASK), stamps
sender+ mintsreply_cap. - Deliver the request to the resolved FlowId (like
Send). - Suspend until a reply hop matches
request_id == request.request_id && sender == resolved_FlowId. - Write the reply
Messageintor[a].
Append-only ABI slot (0x55). No timeout variant in this revision.
Trap = 96
Trap imm → deliberate fault (assertion failure, div-by-zero, bad
opcode encountered by a corrupt/foreign module, capability
violation). Propagates to the Flow supervisor as FlowState::Failed.
Nop = 97
Nop → no-op, used by the assembler to pad jump targets.
Implementations§
Source§impl Opcode
impl Opcode
Sourcepub fn from_u8(byte: u8) -> Option<Opcode>
pub fn from_u8(byte: u8) -> Option<Opcode>
Decode a raw byte into an Opcode, used when loading foreign/untrusted
modules. Rejects anything outside the currently defined ISA rather
than transmuting garbage into a jump-table index (which is exactly
the class of bug that turns a VM into a code-execution primitive).