Skip to main content

Function

Struct Function 

Source
pub struct Function { /* private fields */ }
Expand description

A function body in SSA form: a control-flow graph of basic blocks.

Each block has parameters (the SSA values that flow in along its incoming edges, in place of phi nodes), a sequence of instructions, and one Terminator. Every value is defined once, by a block parameter or an instruction result, and has one Type. The entry block’s parameters are the function’s parameters.

A Function lives in a Module, which holds its declaration (name, Signature, linkage, attributes). It is created and changed through a Builder (Module::build, Module::edit) and read through the accessors here.

Instructions of a block form a linked list over a dense arena, so inserting or removing an instruction is O(1) and handles never move. Removed instructions and blocks leave tombstones; Builder::compact renumbers densely and reports the mapping.

§Examples

use ir_lang::{Linkage, Module, Overflow, Signature, Type};

let mut m = Module::new("demo");
let f = m.declare_function("double", &Signature::new(&[Type::I64], &[Type::I64]), Linkage::Export)?;
let mut b = m.build(f)?;
let x = b.param(0)?;
let y = b.add(x, x, Overflow::Wrap)?;
b.ret(&[y])?;

let func = m.function(f).unwrap();
let entry = func.entry();
assert_eq!(func.block_params(entry), &[x]);
assert_eq!(func.insts(entry).count(), 1);
assert_eq!(func.value_type(y), Some(Type::I64));
m.validate()?;

Implementations§

Source§

impl Function

Source

pub const fn entry(&self) -> Block

The entry block, where execution begins. Its parameters are the function’s parameters, and no edge may target it.

§Examples
use ir_lang::{Linkage, Module, Signature};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let b = m.build(f)?;
assert_eq!(b.func().entry().index(), 0);
Source

pub fn block_count(&self) -> usize

The number of block handles ever created (live and removed): block handles run over 0..block_count().

§Examples
use ir_lang::{Linkage, Module, Signature};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
let _ = b.create_block(&[])?;
assert_eq!(b.func().block_count(), 2);
Source

pub fn blocks(&self) -> impl Iterator<Item = Block> + '_

Iterates over the live blocks in handle order (the entry is block 0 for a function from the builder).

§Examples
use ir_lang::{Linkage, Module, Signature};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
let extra = b.create_block(&[])?;
b.remove_block(extra)?;
assert_eq!(b.func().blocks().count(), 1);
Source

pub fn is_live_block(&self, block: Block) -> bool

Whether block exists and has not been removed.

§Examples
use ir_lang::{Block, Linkage, Module, Signature};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let b = m.build(f)?;
assert!(b.func().is_live_block(Block::from_u32(0)));
assert!(!b.func().is_live_block(Block::from_u32(9)));
Source

pub fn block_params(&self, block: Block) -> &[Value]

The parameters of block, or an empty slice for an unknown block.

§Examples
use ir_lang::{Linkage, Module, Signature, Type};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
let blk = b.create_block(&[Type::Bool, Type::F64])?;
assert_eq!(b.func().block_params(blk).len(), 2);
Source

pub fn insts(&self, block: Block) -> Insts<'_> ⓘ

Iterates over the instructions of block in order (empty for an unknown block). The terminator is not an instruction; see terminator.

§Examples
use ir_lang::{Linkage, Module, Signature, Type};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
let _ = b.iconst(Type::I32, 1)?;
let _ = b.iconst(Type::I32, 2)?;
let entry = b.func().entry();
assert_eq!(b.func().insts(entry).count(), 2);
Source

pub fn first_inst(&self, block: Block) -> Option<Inst>

The first instruction of block, if any.

§Examples
use ir_lang::{Linkage, Module, Signature};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let b = m.build(f)?;
assert_eq!(b.func().first_inst(b.func().entry()), None);
Source

pub fn last_inst(&self, block: Block) -> Option<Inst>

The last instruction of block (before its terminator), if any.

§Examples
use ir_lang::{Linkage, Module, Signature, Type};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
let _ = b.iconst(Type::U8, 1)?;
let entry = b.func().entry();
assert!(b.func().last_inst(entry).is_some());
Source

pub fn next_inst(&self, inst: Inst) -> Option<Inst>

The instruction after inst in its block, if any.

§Examples
use ir_lang::{Linkage, Module, Signature, Type};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
let a = b.iconst(Type::U8, 1)?;
let c = b.iconst(Type::U8, 2)?;
let (ia, ic) = (b.func().defining_inst(a).unwrap(), b.func().defining_inst(c).unwrap());
assert_eq!(b.func().next_inst(ia), Some(ic));
assert_eq!(b.func().prev_inst(ic), Some(ia));
Source

pub fn prev_inst(&self, inst: Inst) -> Option<Inst>

The instruction before inst in its block, if any.

See next_inst for an example.

Source

pub fn inst_count(&self) -> usize

The number of instruction handles ever created (live and removed).

§Examples
use ir_lang::{Linkage, Module, Signature, Type};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
let _ = b.iconst(Type::U8, 1)?;
assert_eq!(b.func().inst_count(), 1);
Source

pub fn inst(&self, inst: Inst) -> Option<&InstData>

The data of inst (also for a removed instruction), or None for an unknown handle.

§Examples
use ir_lang::{InstData, Linkage, Module, Signature, Type};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
let v = b.iconst(Type::I8, -1)?;
let inst = b.func().defining_inst(v).unwrap();
assert_eq!(b.func().inst(inst), Some(&InstData::Const { ty: Type::I8, bits: 0xff }));
Source

pub fn inst_block(&self, inst: Inst) -> Option<Block>

The block containing inst, or None if it was removed or is unknown.

§Examples
use ir_lang::{Linkage, Module, Signature, Type};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
let v = b.iconst(Type::I8, 0)?;
let inst = b.func().defining_inst(v).unwrap();
assert_eq!(b.func().inst_block(inst), Some(b.func().entry()));
Source

pub fn results(&self, inst: Inst) -> ValueRange

The values inst defines (empty for an unknown handle).

§Examples
use ir_lang::{Linkage, Module, Signature, Type};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
let v = b.iconst(Type::I8, 0)?;
let inst = b.func().defining_inst(v).unwrap();
assert_eq!(b.func().results(inst).first(), Some(v));
Source

pub fn terminator(&self, block: Block) -> Option<&Terminator>

The terminator of block, or None if it has none yet (or is unknown).

§Examples
use ir_lang::{Linkage, Module, Signature, Terminator};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
b.unreachable()?;
let entry = b.func().entry();
assert_eq!(b.func().terminator(entry), Some(&Terminator::Unreachable));
Source

pub fn value_count(&self) -> usize

The number of value handles ever created: value handles run over 0..value_count().

§Examples
use ir_lang::{Linkage, Module, Signature, Type};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[Type::I32], &[]), Linkage::Local)?;
let b = m.build(f)?;
assert_eq!(b.func().value_count(), 1);
Source

pub fn value_type(&self, value: Value) -> Option<Type>

The type of value, or None for an unknown handle.

§Examples
use ir_lang::{Linkage, Module, Signature, Type};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[Type::F32], &[]), Linkage::Local)?;
let b = m.build(f)?;
assert_eq!(b.func().value_type(b.param(0)?), Some(Type::F32));
Source

pub fn value_def(&self, value: Value) -> Option<ValueDef>

Where value is defined, or None for an unknown handle.

See ValueDef for an example.

Source

pub fn defining_inst(&self, value: Value) -> Option<Inst>

The instruction defining value, if it is an instruction result.

§Examples
use ir_lang::{Linkage, Module, Signature, Type};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[Type::F32], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
let p = b.param(0)?;
let c = b.iconst(Type::U8, 3)?;
assert!(b.func().defining_inst(c).is_some());
assert!(b.func().defining_inst(p).is_none());
Source

pub fn resolve(&self, value: Value) -> Value

Follows replace_all_uses forwarding: the value every use of value now reads. A value that was never replaced resolves to itself.

Operands stored in instructions are not rewritten eagerly by Builder::replace_all_uses (that keeps it O(1)), so a pass reading operands should resolve them, or call Builder::resolve_aliases once first.

§Examples
use ir_lang::{Linkage, Module, Signature, Type};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
let one = b.iconst(Type::I32, 1)?;
let two = b.iconst(Type::I32, 2)?;
b.replace_all_uses(one, two)?;
assert_eq!(b.func().resolve(one), two);
assert_eq!(b.func().resolve(two), two);
Source

pub fn slot_count(&self) -> usize

The number of stack slots.

§Examples
use ir_lang::{Linkage, Module, Signature};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
let _ = b.stack_slot(8, 8)?;
assert_eq!(b.func().slot_count(), 1);
Source

pub fn slot(&self, slot: StackSlot) -> Option<SlotData>

The size and alignment of a stack slot.

§Examples
use ir_lang::{Linkage, Module, Signature, SlotData};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
let ss = b.stack_slot(24, 8)?;
assert_eq!(b.func().slot(ss), Some(SlotData { size: 24, align: 8 }));
Source

pub fn predecessors(&self) -> Vec<Vec<Block>>

The predecessor blocks of every block, indexed by block handle, listing a predecessor once per edge (a branch with both edges to one block lists it twice). Only live blocks contribute edges.

§Examples
use ir_lang::{Linkage, Module, Signature};

let mut m = Module::new("m");
let f = m.declare_function("f", &Signature::new(&[], &[]), Linkage::Local)?;
let mut b = m.build(f)?;
let exit = b.create_block(&[])?;
b.jump(exit, &[])?;
b.switch_to(exit)?;
b.ret(&[])?;
let preds = b.func().predecessors();
assert_eq!(preds[exit.index()], [b.func().entry()]);

Trait Implementations§

Source§

impl Clone for Function

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for Function

Source§

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

Formats the value using the given formatter. Read more

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 = !

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

fn try_from(value: U) -> Result<T, !>

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.