support zero-sized values (empty record, unit type)

They now use no stack space
This commit is contained in:
Folkert 2020-03-19 11:24:44 +01:00
parent b93fe4e341
commit 9d1e2a0ef1
3 changed files with 59 additions and 3 deletions

View file

@ -27,6 +27,10 @@ pub enum ScopeEntry {
Heap { expr_type: Type, ptr: Value },
Arg { expr_type: Type, param: Value },
Func { sig: Signature, func_id: FuncId },
// For empty records and unit types, storing is a no-op and values can be created "out of thin
// air". No need to use stack space for them.
ZeroSized,
}
pub struct Env<'a> {
@ -101,13 +105,21 @@ pub fn build_expr<'a, B: Backend>(
let mut scope = im_rc::HashMap::clone(scope);
let cfg = env.cfg;
let ptr_size = cfg.pointer_bytes() as u32;
for (name, layout, expr) in stores.iter() {
let stack_size = layout.stack_size(ptr_size);
if stack_size == 0 {
scope.insert(*name, ScopeEntry::ZeroSized);
continue;
}
let val = build_expr(env, &scope, module, builder, &expr, procs);
let expr_type = type_from_layout(cfg, &layout);
let slot = builder.create_stack_slot(StackSlotData::new(
StackSlotKind::ExplicitSlot,
layout.stack_size(cfg.pointer_bytes() as u32),
stack_size,
));
builder.ins().stack_store(val, slot, Offset32::new(0));
@ -168,6 +180,17 @@ pub fn build_expr<'a, B: Backend>(
Some(ScopeEntry::Func { .. }) => {
panic!("TODO I don't yet know how to return fn pointers")
}
Some(ScopeEntry::ZeroSized) => {
// Create a slot
let slot = builder.create_stack_slot(StackSlotData::new(
StackSlotKind::ExplicitSlot,
0
));
builder
.ins()
.stack_addr(env.cfg.pointer_type(), slot, Offset32::new(0))
}
None => panic!(
"Could not resolve lookup for {:?} because no ScopeEntry was found for {:?} in scope {:?}",
name, name, scope

View file

@ -227,8 +227,6 @@ mod test_gen {
// Populate Procs and get the low-level Expr from the canonical Expr
let main_body = Expr::new(&arena, &mut subs, loc_expr.value, &mut procs, home, &mut ident_ids, POINTER_SIZE);
dbg!(&main_body);
// Put this module's ident_ids back in the interns, so we can use them in Env.
env.interns.all_ident_ids.insert(home, ident_ids);
@ -1313,6 +1311,39 @@ mod test_gen {
);
}
#[test]
fn empty_record() {
assert_evals_to!(
indoc!(
r#"
v = {}
1
"#
),
1,
i64
);
}
#[test]
fn unit_type() {
assert_evals_to!(
indoc!(
r#"
Unit : [ Unit ]
v : Unit
v = Unit
1
"#
),
1,
i64
);
}
#[test]
fn basic_record() {
assert_evals_to!(

View file

@ -672,6 +672,8 @@ fn from_can<'a>(
Expr::Struct(field_tuples.into_bump_slice())
}
EmptyRecord => Expr::Struct(&[]),
Tag {
variant_var,
name: tag_name,