pub struct Compiled { /* private fields */ }Expand description
A compiled unit: the LSB module, its entry points, and the map from every instruction back to the HIR node it was compiled from.
§Examples
use hir_lang::{Builder, Name};
use intern_lang::Interner;
let mut names = Interner::new();
let mut b = Builder::new();
let one = b.int(1);
let body = b.block(&[], Some(one));
let f = b.func(Name::new(names.intern("one")), &[], body);
let root = b.module(None, &[f]);
let hir = b.finish(root)?;
let out = bcgen_lang::compile(&hir, &names)?;
let func = out.function(f).unwrap();
// Every instruction maps back to a node of the unit.
for pc in 0..out.module().function(func).unwrap().code().len() {
assert!(out.origin(func, pc as u32).is_some());
}Implementations§
Source§impl Compiled
impl Compiled
Sourcepub fn module(&self) -> &Module
pub fn module(&self) -> &Module
The LSB module.
§Examples
let hir = { let mut b = hir_lang::Builder::new(); let r = b.module(None, &[]); b.finish(r)? };
let out = bcgen_lang::compile(&hir, &intern_lang::Interner::new())?;
assert_eq!(out.module().functions().len(), 1); // the entrySourcepub fn into_module(self) -> Module
pub fn into_module(self) -> Module
The LSB module, by value (to hand to a VM or an encoder).
§Examples
let hir = { let mut b = hir_lang::Builder::new(); let r = b.module(None, &[]); b.finish(r)? };
let module = bcgen_lang::compile(&hir, &intern_lang::Interner::new())?.into_module();
assert!(!bytecode_lang::encode(&module).is_empty());Sourcepub fn entry(&self) -> FuncId
pub fn entry(&self) -> FuncId
The entry function, () -> dyn, exported as <entry>: it returns the
value of the module body (nil without one). Under
BodyMode::Start the body runs once, in the
start function, and the entry reads its kept value; under
BodyMode::Entry the entry is the body.
§Examples
let hir = { let mut b = hir_lang::Builder::new(); let r = b.module(None, &[]); b.finish(r)? };
let out = bcgen_lang::compile(&hir, &intern_lang::Interner::new())?;
assert!(out.module().function(out.entry()).is_some());Sourcepub fn start(&self) -> Option<FuncId>
pub fn start(&self) -> Option<FuncId>
The module’s start function, if it has one: global and constant
initializers, defaults evaluated once, and (under BodyMode::Start)
the body.
§Examples
let hir = { let mut b = hir_lang::Builder::new(); let r = b.module(None, &[]); b.finish(r)? };
assert_eq!(bcgen_lang::compile(&hir, &intern_lang::Interner::new())?.start(), None);Sourcepub fn result_global(&self) -> Option<GlobalId>
pub fn result_global(&self) -> Option<GlobalId>
The global holding the module body’s value under BodyMode::Start.
§Examples
let hir = { let mut b = hir_lang::Builder::new(); let r = b.module(None, &[]); b.finish(r)? };
assert!(bcgen_lang::compile(&hir, &intern_lang::Interner::new())?.result_global().is_none());Sourcepub fn function(&self, item: ItemId) -> Option<FuncId>
pub fn function(&self, item: ItemId) -> Option<FuncId>
The function compiled for a HIR function item: its parameters are
dyn (a by-reference parameter is a ref cell dyn holding an LSB
reference), followed by an i64 presence mask when any parameter has
a default; it returns dyn (a generator’s returns its coroutine). It
carries the item’s LSB parameter list, so it can be called typed
(call, Vm::run) or bound dynamically. Root-level functions are
exported under their names.
§Examples
See Compiled.
Sourcepub fn origins(&self, func: FuncId) -> &[NodeRef]
pub fn origins(&self, func: FuncId) -> &[NodeRef]
The HIR node of every instruction of func, indexed by pc.
§Examples
let hir = { let mut b = hir_lang::Builder::new(); let r = b.module(None, &[]); b.finish(r)? };
let out = bcgen_lang::compile(&hir, &intern_lang::Interner::new())?;
assert_eq!(out.origins(out.entry()).len(), out.module().function(out.entry()).unwrap().code().len());Sourcepub fn class_type(&self, class: ItemId) -> Option<TypeId>
pub fn class_type(&self, class: ItemId) -> Option<TypeId>
The LSB struct type of a class or interface item (mixins have none).
§Examples
use hir_lang::{Builder, ClassDef, Generics, Item, ItemKind, List, Name};
use intern_lang::Interner;
let mut names = Interner::new();
let mut b = Builder::new();
let class = ClassDef {
generics: Generics::default(),
bases: List::EMPTY,
interfaces: List::EMPTY,
fields: List::EMPTY,
items: List::EMPTY,
is_abstract: false,
is_final: false,
mixin: false,
};
let c = b.item(Item::new(Some(Name::new(names.intern("Point"))), ItemKind::Class(class)));
let root = b.module(None, &[c]);
let out = bcgen_lang::compile(&b.finish(root)?, &names)?;
let ty = out.class_type(c).unwrap();
assert!(matches!(out.module().types()[ty.index()], bytecode_lang::TypeDef::Struct(_)));Sourcepub fn method(&self, class: ItemId, method: ItemId) -> Option<FuncId>
pub fn method(&self, class: ItemId, method: ItemId) -> Option<FuncId>
The function a method item was compiled to for a class (a mixin’s method has one per class using it; an abstract method has none).
§Examples
See tests/classes.rs; a class without methods has none:
let hir = { let mut b = hir_lang::Builder::new(); let r = b.module(None, &[]); b.finish(r)? };
let out = bcgen_lang::compile(&hir, &intern_lang::Interner::new())?;
assert_eq!(out.method(hir.root(), hir.root()), None);Sourcepub fn destructor(&self) -> Option<&str>
pub fn destructor(&self) -> Option<&str>
The LSB method name of the destructor
(Options::destructor, __destruct()
in the PHP profile), when a class of the unit defines one. LSB format
2 has no destructor flag: the host passes this name to bvm-lang’s
Vm::set_destructor on a VM made with the reference-counting memory
profile, so destructors run where PHP runs them.
§Examples
let hir = { let mut b = hir_lang::Builder::new(); let r = b.module(None, &[]); b.finish(r)? };
let out = bcgen_lang::compile(&hir, &intern_lang::Interner::new())?;
assert_eq!(out.destructor(), None);