mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
support zero-sized values (empty record, unit type)
They now use no stack space
This commit is contained in:
parent
b93fe4e341
commit
9d1e2a0ef1
3 changed files with 59 additions and 3 deletions
|
@ -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
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -672,6 +672,8 @@ fn from_can<'a>(
|
|||
Expr::Struct(field_tuples.into_bump_slice())
|
||||
}
|
||||
|
||||
EmptyRecord => Expr::Struct(&[]),
|
||||
|
||||
Tag {
|
||||
variant_var,
|
||||
name: tag_name,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue