#[non_exhaustive]pub enum Terminator {
Jump(BlockCall),
Branch {
cond: Value,
then_dest: BlockCall,
else_dest: BlockCall,
},
Switch {
value: Value,
cases: Vec<SwitchCase>,
default: BlockCall,
},
Return {
values: Vec<Value>,
},
Unreachable,
Trap {
code: u32,
},
TailCall(Box<Call>),
Invoke {
call: Box<Call>,
normal: BlockCall,
unwind: BlockCall,
},
Check {
op: Box<InstData>,
normal: BlockCall,
error: BlockCall,
},
Resume {
payload: Value,
},
}Expand description
The instruction that ends a block and says where control goes next.
§Examples
use ir_lang::{Block, BlockCall, Terminator};
let t = Terminator::Jump(BlockCall::new(Block::from_u32(1), &[]));
assert_eq!(t.successors().count(), 1);
assert!(Terminator::Unreachable.successors().next().is_none());Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Jump(BlockCall)
Unconditional jump.
Branch
Two-way branch on a bool.
Fields
Switch
Multi-way branch on an integer; case values are distinct.
Fields
cases: Vec<SwitchCase>The cases.
Return
Return from the function with values matching its signature’s returns.
Unreachable
Control never reaches here; reaching it is undefined behaviour.
Trap
Abort the program deterministically with code (OPS §6 codes 1–5 for
operation errors; other codes are the language’s own).
TailCall(Box<Call>)
A tail call: the callee’s returns become this function’s returns. The
callee’s convention and returns must equal this function’s; gc must be
empty (the frame is gone).
Invoke
A call with an exception edge: on normal return control goes to normal,
if the callee unwinds it goes to unwind, a landing pad.
Fields
Check
An operation whose policy has an error field (or char_from_u32): on
success control goes to normal (its result is Result(0)); on failure to
error with the error code as ErrorCode.
Fields
Resume
Unwind out of this function with payload (a ptr): rethrows after
cleanup in a landing pad, or raises an exception the runtime prepared.
Implementations§
Source§impl Terminator
impl Terminator
Sourcepub fn successors(&self) -> Successors<'_> ⓘ
pub fn successors(&self) -> Successors<'_> ⓘ
The outgoing edges, in a fixed order (switch cases first, then the
default; then before else; normal before unwind/error).
§Examples
use ir_lang::{Block, BlockCall, Terminator, Value};
let t = Terminator::Branch {
cond: Value::from_u32(0),
then_dest: BlockCall::new(Block::from_u32(1), &[]),
else_dest: BlockCall::new(Block::from_u32(2), &[]),
};
let targets: Vec<_> = t.successors().map(|c| c.block.index()).collect();
assert_eq!(targets, [1, 2]);Sourcepub fn for_each_successor_mut(&mut self, f: impl FnMut(&mut BlockCall))
pub fn for_each_successor_mut(&mut self, f: impl FnMut(&mut BlockCall))
Mutable access to the outgoing edges, in the same order as
successors.
§Examples
use ir_lang::{Block, BlockCall, Terminator};
let mut t = Terminator::Jump(BlockCall::new(Block::from_u32(1), &[]));
t.for_each_successor_mut(|c| c.block = Block::from_u32(5));
assert_eq!(t.successors().next().unwrap().block, Block::from_u32(5));Sourcepub fn for_each_operand(&self, f: impl FnMut(Value))
pub fn for_each_operand(&self, f: impl FnMut(Value))
Calls f on every SSA value the terminator reads, including the values
passed along its edges.
§Examples
use ir_lang::{Terminator, Value};
let mut n = 0;
Terminator::Return { values: vec![Value::from_u32(0)] }.for_each_operand(|_| n += 1);
assert_eq!(n, 1);Sourcepub fn map_operands(&mut self, f: impl FnMut(Value) -> Value)
pub fn map_operands(&mut self, f: impl FnMut(Value) -> Value)
Rewrites every SSA value the terminator reads, including edge arguments.
§Examples
use ir_lang::{Terminator, Value};
let mut t = Terminator::Resume { payload: Value::from_u32(0) };
t.map_operands(|_| Value::from_u32(9));
assert_eq!(t, Terminator::Resume { payload: Value::from_u32(9) });