Skip to main content

Function

Struct Function 

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

A function in SSA form: a control-flow graph of basic blocks over a single flat store of values.

A function is the unit ir-lang represents and the thing a front-end lowers into. It has a name, a parameter list, a return type, an entry block, and a set of blocks; each block is a run of value-producing Insts ended by one Terminator. Values are named by Value handles and defined exactly once, either as a block parameter or as an instruction result.

You do not construct a Function field by field — a Builder produces one. Once you hold it, the accessors here read it back, and validate checks it is well-formed. A function also prints as a readable textual IR through its Display implementation.

§Examples

use ir_lang::{Builder, BinOp, Type};

// fn double(x: int) -> int { x + x }
let mut b = Builder::new("double", &[Type::Int], Type::Int);
let x = b.block_params(b.entry())[0];
let sum = b.bin(BinOp::Add, x, x);
b.ret(Some(sum));
let func = b.finish();

assert_eq!(func.name(), "double");
assert_eq!(func.params(), &[Type::Int]);
assert_eq!(func.ret(), Type::Int);
assert!(func.validate().is_ok());

Implementations§

Source§

impl Function

Source

pub fn name(&self) -> &str

Returns the function’s name.

§Examples
use ir_lang::{Builder, Type};

let b = Builder::new("main", &[], Type::Unit);
assert_eq!(b.finish().name(), "main");
Source

pub fn params(&self) -> &[Type]

Returns the function’s parameter types, in order. These are also the types of the entry block’s parameters.

§Examples
use ir_lang::{Builder, Type};

let b = Builder::new("f", &[Type::Int, Type::Bool], Type::Unit);
assert_eq!(b.finish().params(), &[Type::Int, Type::Bool]);
Source

pub const fn ret(&self) -> Type

Returns the function’s return type.

§Examples
use ir_lang::{Builder, Type};

let b = Builder::new("f", &[], Type::Float);
assert_eq!(b.finish().ret(), Type::Float);
Source

pub const fn entry(&self) -> Block

Returns the entry block — where execution begins. It is always block zero and its parameters are the function’s parameters.

§Examples
use ir_lang::{Builder, Type, Block};

let b = Builder::new("f", &[], Type::Unit);
assert_eq!(b.finish().entry().index(), 0);
Source

pub fn block_count(&self) -> usize

Returns the number of blocks in the function.

§Examples
use ir_lang::{Builder, Type};

let mut b = Builder::new("f", &[], Type::Unit);
let _ = b.create_block(&[]);
b.ret(None);
assert_eq!(b.finish().block_count(), 2);
Source

pub fn value_count(&self) -> usize

Returns the number of values defined in the function (block parameters and instruction results together). Value handles run densely over 0..count.

§Examples
use ir_lang::{Builder, Type};

let mut b = Builder::new("f", &[Type::Int], Type::Int);
let one = b.iconst(1);
b.ret(Some(one));
// one parameter value + one constant value
assert_eq!(b.finish().value_count(), 2);
Source

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

Iterates over every block handle, entry first, in creation order.

§Examples
use ir_lang::{Builder, Type};

let mut b = Builder::new("f", &[], Type::Unit);
let _ = b.create_block(&[]);
b.ret(None);
let func = b.finish();
assert_eq!(func.blocks().count(), 2);
Source

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

Returns a block’s parameter values, in order, or an empty slice if the block handle is out of range.

§Examples
use ir_lang::{Builder, Type};

let b = Builder::new("f", &[Type::Int, Type::Int], Type::Unit);
let func = b.finish();
assert_eq!(func.block_params(func.entry()).len(), 2);
Source

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

Returns the values defined by a block’s instructions, in program order, or an empty slice if the block handle is out of range.

§Examples
use ir_lang::{Builder, BinOp, Type};

let mut b = Builder::new("f", &[Type::Int], Type::Int);
let x = b.block_params(b.entry())[0];
let _ = b.bin(BinOp::Add, x, x);
b.ret(Some(x));
let func = b.finish();
assert_eq!(func.insts(func.entry()).len(), 1);
Source

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

Returns a block’s terminator, or None if the block handle is out of range or no terminator was set (an unterminated block — which validate rejects).

§Examples
use ir_lang::{Builder, Type, Terminator};

let mut b = Builder::new("f", &[], Type::Unit);
b.ret(None);
let func = b.finish();
assert!(matches!(func.terminator(func.entry()), Some(Terminator::Return(None))));
Source

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

Returns the instruction that defined a value, or None if the value is a block parameter or the handle is out of range.

§Examples
use ir_lang::{Builder, Inst, Type};

let mut b = Builder::new("f", &[Type::Int], Type::Int);
let param = b.block_params(b.entry())[0];
let five = b.iconst(5);
b.ret(Some(param));
let func = b.finish();

assert!(matches!(func.inst(five), Some(Inst::Iconst(5))));
assert!(func.inst(param).is_none()); // a parameter has no defining instruction
Source

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

Returns the type of a value, or None if the handle is out of range.

§Examples
use ir_lang::{Builder, BinOp, Type};

let mut b = Builder::new("f", &[Type::Int], Type::Bool);
let x = b.block_params(b.entry())[0];
let cmp = b.bin(BinOp::Lt, x, x);
b.ret(Some(cmp));
let func = b.finish();

assert_eq!(func.value_type(x), Some(Type::Int));
assert_eq!(func.value_type(cmp), Some(Type::Bool));
Source

pub fn value_block(&self, value: Value) -> Option<Block>

Returns the block a value is defined in, or None if the handle is out of range.

§Examples
use ir_lang::{Builder, Type};

let mut b = Builder::new("f", &[Type::Int], Type::Int);
let x = b.block_params(b.entry())[0];
b.ret(Some(x));
let func = b.finish();
assert_eq!(func.value_block(x), Some(func.entry()));
Source

pub fn validate(&self) -> Result<(), ValidationError>

Checks that the function is well-formed, returning the first violation found.

A function that validates satisfies the SSA invariants the rest of a compiler relies on: every block ends in exactly one terminator; every branch targets a real block with a matching number and type of arguments; every value is referenced only where its single definition reaches it; operations are applied to operands of the right type; and the entry block is never a branch target. The Builder does not check these as it goes, so run this once construction is complete — and again on the output of any pass that rewrites the IR.

§Errors

Returns the first ValidationError encountered. Each variant names the offending block or value; see ValidationError for the meaning of each and how to fix it.

§Examples
use ir_lang::{Builder, BinOp, Type, ValidationError};

// A well-formed function validates.
let mut b = Builder::new("f", &[Type::Int], Type::Int);
let x = b.block_params(b.entry())[0];
let two = b.iconst(2);
let doubled = b.bin(BinOp::Mul, x, two);
b.ret(Some(doubled));
assert!(b.finish().validate().is_ok());

// A block with no terminator does not.
let unfinished = Builder::new("g", &[], Type::Unit).finish();
assert!(matches!(
    unfinished.validate(),
    Err(ValidationError::MissingTerminator { .. })
));

Trait Implementations§

Source§

impl Clone for Function

Source§

fn clone(&self) -> Function

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
Source§

impl<'de> Deserialize<'de> for Function

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Display for Function

Source§

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

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

impl PartialEq for Function

Source§

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

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · 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 Serialize for Function

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for Function

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> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

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> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. 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.