pub struct Program { /* private fields */ }Expand description
A lowered function: a flat bytecode program ready to be inspected, serialized, or run.
A program is produced by a Backend — for the bytecode target, by
Bytecode or the compile shortcut. It owns
the function’s name, the registers holding its parameters, a count of every register
it uses, and the op stream. Control-flow ops refer to positions in
that stream through Labels, which label_offset
resolves to op indices. Execution begins at the first op, the entry
block.
The Display implementation renders the program as a readable
disassembly, which is the easiest way to see what a backend produced.
§Examples
use codegen_lang::compile;
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 program = compile(&b.finish()).expect("double is well-formed");
assert_eq!(program.name(), "double");
assert_eq!(program.params().len(), 1);
assert_eq!(program.register_count(), 2); // x and the sum
assert!(!program.is_empty());Implementations§
Source§impl Program
impl Program
Sourcepub fn name(&self) -> &str
pub fn name(&self) -> &str
Returns the function’s name.
§Examples
use codegen_lang::compile;
use ir_lang::{Builder, Type};
let mut b = Builder::new("main", &[], Type::Unit);
b.ret(None);
assert_eq!(compile(&b.finish()).unwrap().name(), "main");Sourcepub fn params(&self) -> &[Reg]
pub fn params(&self) -> &[Reg]
Returns the registers holding the function’s parameters, in declaration order.
These are the registers an interpreter writes the call arguments into before it begins executing the op stream.
§Examples
use codegen_lang::compile;
use ir_lang::{Builder, Type};
let mut b = Builder::new("f", &[Type::Int, Type::Bool], Type::Unit);
b.ret(None);
let program = compile(&b.finish()).unwrap();
assert_eq!(program.params().len(), 2);Sourcepub const fn register_count(&self) -> u32
pub const fn register_count(&self) -> u32
Returns the number of registers the program uses; valid register numbers are
0..register_count.
§Examples
use codegen_lang::compile;
use ir_lang::{Builder, Type};
let mut b = Builder::new("f", &[Type::Int], Type::Int);
let x = b.block_params(b.entry())[0];
let one = b.iconst(1);
let r = b.bin(ir_lang::BinOp::Add, x, one);
b.ret(Some(r));
// x, the constant, and the sum.
assert_eq!(compile(&b.finish()).unwrap().register_count(), 3);Sourcepub fn ops(&self) -> &[Op]
pub fn ops(&self) -> &[Op]
Returns the program’s ops, in execution order.
§Examples
use codegen_lang::{compile, Op};
use ir_lang::{Builder, Type};
let mut b = Builder::new("f", &[], Type::Unit);
b.ret(None);
let program = compile(&b.finish()).unwrap();
assert!(matches!(program.ops(), [Op::Return { value: None }]));Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true if the program has no ops. A program lowered from a valid function
is never empty: its entry block always ends in a terminator op.
Sourcepub fn label_offset(&self, label: Label) -> Option<usize>
pub fn label_offset(&self, label: Label) -> Option<usize>
Resolves a label to the index of the op it points at, or None if the label does
not belong to this program.
§Examples
use codegen_lang::compile;
use ir_lang::{Builder, Type};
let mut b = Builder::new("f", &[], Type::Unit);
b.ret(None);
let program = compile(&b.finish()).unwrap();
// Execution starts at the entry label, which is the first op.
assert_eq!(program.label_offset(program.entry()), Some(0));