ControlInstruction

Enum ControlInstruction 

Source
pub enum ControlInstruction {
    Nop,
    Unreachable,
    Block(BlockType, Expression),
    Loop(BlockType, Expression),
    If(BlockType, Expression, Option<Expression>),
    Branch(LabelIndex),
    BranchIf(LabelIndex),
    BranchTable(Vec<LabelIndex>, LabelIndex),
    Return,
    Call(FunctionIndex),
    CallIndirect(TypeIndex, TableIndex),
}
Expand description

Instructions in this group affect the flow of control. The π–»π—…π—ˆπ–Όπ—„, π—…π—ˆπ—ˆπ—‰ and 𝗂𝖿 instructions are structured instructions. They bracket nested sequences of instructions, called blocks, terminated with, or separated by, 𝖾𝗇𝖽 or π–Ύπ—…π—Œπ–Ύ pseudo-instructions. As the grammar prescribes, they must be well-nested.

A structured instruction can consume input and produce output on the operand stack according to its annotated block type. It is given either as a type index that refers to a suitable function type, or as an optional value type inline, which is a shorthand for the function type []β†’[valtype?].

Each structured control instruction introduces an implicit label. Labels are targets for branch instructions that reference them with label indices. Unlike with other index spaces, indexing of labels is relative by nesting depth, that is, label 0 refers to the innermost structured control instruction enclosing the referring branch instruction, while increasing indices refer to those farther out. Consequently, labels can only be referenced from within the associated structured control instruction. This also implies that branches can only be directed outwards, β€œbreaking” from the block of the control construct they target. The exact effect depends on that control construct. In case of π–»π—…π—ˆπ–Όπ—„ or 𝗂𝖿 it is a forward jump, resuming execution after the matching 𝖾𝗇𝖽. In case of π—…π—ˆπ—ˆπ—‰ it is a backward jump to the beginning of the loop.

Taking a branch unwinds the operand stack up to the height where the targeted structured control instruction was entered. However, branches may additionally consume operands themselves, which they push back on the operand stack after unwinding. Forward branches require operands according to the output of the targeted block’s type, i.e., represent the values produced by the terminated block. Backward branches require operands according to the input of the targeted block’s type, i.e., represent the values consumed by the restarted block.

See https://webassembly.github.io/spec/core/syntax/instructions.html#control-instructions

Β§Examples

Β§Simple

use wasm_ast::{ControlInstruction, Instruction};

assert_eq!(Instruction::Control(ControlInstruction::Nop), ControlInstruction::Nop.into());
assert_eq!(Instruction::Control(ControlInstruction::Unreachable), ControlInstruction::Unreachable.into());
assert_eq!(Instruction::Control(ControlInstruction::Branch(0)), ControlInstruction::Branch(0).into());
assert_eq!(Instruction::Control(ControlInstruction::BranchIf(1)), ControlInstruction::BranchIf(1).into());
assert_eq!(Instruction::Control(ControlInstruction::BranchTable(vec![0], 1)), ControlInstruction::BranchTable(vec![0], 1).into());
assert_eq!(Instruction::Control(ControlInstruction::Return), ControlInstruction::Return.into());
assert_eq!(Instruction::Control(ControlInstruction::Call(1)), ControlInstruction::Call(1).into());
assert_eq!(Instruction::Control(ControlInstruction::CallIndirect(0, 1)), ControlInstruction::CallIndirect(0, 1).into());

Β§Block

use wasm_ast::{ControlInstruction, Instruction, Expression, BlockType, ValueType};

let expression = Expression::new(vec![ControlInstruction::Nop.into(), 0i32.into()]);

assert_eq!(
    Instruction::Control(ControlInstruction::Block(BlockType::ValueType(ValueType::I32), expression.clone())),
    ControlInstruction::Block(BlockType::ValueType(ValueType::I32), expression.clone()).into()
);

Β§Loop

use wasm_ast::{ControlInstruction, Instruction, BlockType, Expression};
let expression = Expression::new(vec![ControlInstruction::Nop.into(), 0i32.into()]);

assert_eq!(
    Instruction::Control(ControlInstruction::Loop(BlockType::Index(0), expression.clone())),
    ControlInstruction::Loop(BlockType::Index(0), expression.clone()).into()
);

Β§If

use wasm_ast::{ControlInstruction, Instruction, Expression, BlockType};
let expression = Expression::new(vec![ControlInstruction::Nop.into()]);

assert_eq!(
    Instruction::Control(ControlInstruction::If(BlockType::None, expression.clone(), None)),
    ControlInstruction::If(BlockType::None, expression.clone(), None).into()
);

assert_eq!(
    Instruction::Control(ControlInstruction::If(BlockType::None, expression.clone(), Some(expression.clone()))),
    ControlInstruction::If(BlockType::None, expression.clone(), Some(expression.clone())).into()
);

VariantsΒ§

Β§

Nop

The π—‡π—ˆπ—‰ instruction does nothing.

Β§

Unreachable

The π—Žπ—‡π—‹π–Ύπ–Ίπ–Όπ—π–Ίπ–»π—…π–Ύ instruction causes an unconditional trap.

Β§

Block(BlockType, Expression)

A logical grouping used introduce a label around an expression.

Β§

Loop(BlockType, Expression)

Executes the expression in a loop.

Β§

If(BlockType, Expression, Option<Expression>)

Conditionally executes a positive or (optional) negative branch based on a test value.

Β§

Branch(LabelIndex)

The 𝖻𝗋 instruction performs an unconditional branch.

Β§

BranchIf(LabelIndex)

The 𝖻𝗋_𝗂𝖿 instruction performs a conditional branch

Β§

BranchTable(Vec<LabelIndex>, LabelIndex)

The 𝖻𝗋_𝗍𝖺𝖻𝗅𝖾 instruction performs an indirect branch through an operand indexing into the label vector that is an immediate to the instruction, or to a default target if the operand is out of bounds.

Β§

Return

The π—‹π–Ύπ—π—Žπ—‹π—‡ instruction is a shortcut for an unconditional branch to the outermost block, which implicitly is the body of the current function.

Β§

Call(FunctionIndex)

The 𝖼𝖺𝗅𝗅 instruction invokes another function, consuming the necessary arguments from the stack and returning the result values of the call.

Β§

CallIndirect(TypeIndex, TableIndex)

The 𝖼𝖺𝗅𝗅_𝗂𝗇𝖽𝗂𝗋𝖾𝖼𝗍 instruction calls a function indirectly through an operand indexing into a table that is denoted by a table index and must have type π–Ώπ—Žπ—‡π–Όπ—‹π–Ύπ–Ώ. Since it may contain functions of heterogeneous type, the callee is dynamically checked against the function type indexed by the instruction’s second immediate, and the call is aborted with a trap if it does not match.

Trait ImplementationsΒ§

SourceΒ§

impl Clone for ControlInstruction

SourceΒ§

fn clone(&self) -> ControlInstruction

Returns a duplicate of the value. Read more
1.0.0 Β· SourceΒ§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
SourceΒ§

impl Debug for ControlInstruction

SourceΒ§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
SourceΒ§

impl From<ControlInstruction> for Instruction

SourceΒ§

fn from(instruction: ControlInstruction) -> Self

Converts to this type from the input type.
SourceΒ§

impl PartialEq for ControlInstruction

SourceΒ§

fn eq(&self, other: &ControlInstruction) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 Β· SourceΒ§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
SourceΒ§

impl StructuralPartialEq for ControlInstruction

Auto Trait ImplementationsΒ§

Blanket ImplementationsΒ§

SourceΒ§

impl<T> Any for T
where T: 'static + ?Sized,

SourceΒ§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
SourceΒ§

impl<T> Borrow<T> for T
where T: ?Sized,

SourceΒ§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
SourceΒ§

impl<T> BorrowMut<T> for T
where T: ?Sized,

SourceΒ§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
SourceΒ§

impl<T> CloneToUninit for T
where T: Clone,

SourceΒ§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

πŸ”¬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
SourceΒ§

impl<T> From<T> for T

SourceΒ§

fn from(t: T) -> T

Returns the argument unchanged.

SourceΒ§

impl<T, U> Into<U> for T
where U: From<T>,

SourceΒ§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

SourceΒ§

impl<T> ToOwned for T
where T: Clone,

SourceΒ§

type Owned = T

The resulting type after obtaining ownership.
SourceΒ§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
SourceΒ§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
SourceΒ§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

SourceΒ§

type Error = Infallible

The type returned in the event of a conversion error.
SourceΒ§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
SourceΒ§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

SourceΒ§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
SourceΒ§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.