#[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).
pub fn as_u8(self) -> u8
Trait Implementations§
impl Copy for Opcode
impl Eq for Opcode
impl StructuralPartialEq for Opcode
Auto Trait Implementations§
impl Freeze for Opcode
impl RefUnwindSafe for Opcode
impl Send for Opcode
impl Sync for Opcode
impl Unpin for Opcode
impl UnsafeUnpin for Opcode
impl UnwindSafe for Opcode
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.