emit less MultiTagUnion

This commit is contained in:
Folkert 2021-06-21 20:56:03 +02:00
parent 5734cce250
commit cc93da006d
5 changed files with 31 additions and 18 deletions

View file

@ -1036,8 +1036,8 @@ fn path_to_expr_help<'a>(
let mut it = instructions.iter().peekable(); let mut it = instructions.iter().peekable();
while let Some(PathInstruction { index, tag_id }) = it.next() { while let Some(PathInstruction { index, tag_id }) = it.next() {
match Wrapped::opt_from_layout(&layout) { match Wrapped::is_indexable(&layout) {
None => { false => {
// this MUST be an index into a single-element (hence unwrapped) record // this MUST be an index into a single-element (hence unwrapped) record
debug_assert_eq!(*index, 0, "{:?}", &layout); debug_assert_eq!(*index, 0, "{:?}", &layout);
@ -1063,7 +1063,7 @@ fn path_to_expr_help<'a>(
break; break;
} }
Some(wrapped) => { true => {
let index = *index; let index = *index;
let (inner_layout, inner_expr) = match layout { let (inner_layout, inner_expr) = match layout {
@ -1078,6 +1078,7 @@ fn path_to_expr_help<'a>(
(union_layout.layout_at(*tag_id as u8, index as usize), expr) (union_layout.layout_at(*tag_id as u8, index as usize), expr)
} }
Layout::Struct(field_layouts) => { Layout::Struct(field_layouts) => {
let wrapped = Wrapped::opt_from_layout(&layout).unwrap();
debug_assert!(field_layouts.len() > 1); debug_assert!(field_layouts.len() > 1);
debug_assert_eq!(wrapped, Wrapped::RecordOrSingleTagUnion); debug_assert_eq!(wrapped, Wrapped::RecordOrSingleTagUnion);

View file

@ -1032,6 +1032,17 @@ impl Wrapped {
} }
} }
pub fn is_indexable(layout: &Layout<'_>) -> bool {
match layout {
Layout::Struct(fields) => match fields.len() {
_ => true,
},
Layout::Union(variant) => true,
_ => false,
}
}
pub fn opt_from_layout(layout: &Layout<'_>) -> Option<Self> { pub fn opt_from_layout(layout: &Layout<'_>) -> Option<Self> {
match layout { match layout {
Layout::Struct(fields) => match fields.len() { Layout::Struct(fields) => match fields.len() {
@ -1056,6 +1067,7 @@ impl Wrapped {
NonNullableUnwrapped(_) => Some(Wrapped::LikeARoseTree), NonNullableUnwrapped(_) => Some(Wrapped::LikeARoseTree),
NullableWrapped { .. } | NullableUnwrapped { .. } => { NullableWrapped { .. } | NullableUnwrapped { .. } => {
todo!();
Some(Wrapped::MultiTagUnion) Some(Wrapped::MultiTagUnion)
} }
} }
@ -2133,6 +2145,8 @@ fn specialize_external<'a>(
match closure_layout.layout_for_member(proc_name) { match closure_layout.layout_for_member(proc_name) {
ClosureRepresentation::Union { ClosureRepresentation::Union {
tag_layout: field_layouts, tag_layout: field_layouts,
union_layout,
tag_id,
.. ..
} => { } => {
debug_assert_eq!(field_layouts.len() - 1, captured.len()); debug_assert_eq!(field_layouts.len() - 1, captured.len());
@ -2143,11 +2157,11 @@ fn specialize_external<'a>(
index += 1; index += 1;
// TODO therefore should the wrapped here not be RecordOrSingleTagUnion? // TODO therefore should the wrapped here not be RecordOrSingleTagUnion?
let expr = Expr::AccessAtIndex { let expr = Expr::CoerceToTagId {
index: index as _, tag_id,
field_layouts,
structure: Symbol::ARG_CLOSURE, structure: Symbol::ARG_CLOSURE,
wrapped, index: index as _,
union_layout,
}; };
let layout = field_layouts[index]; let layout = field_layouts[index];
@ -4074,21 +4088,17 @@ fn construct_closure_data<'a>(
tag_layout: _, tag_layout: _,
union_size, union_size,
tag_name, tag_name,
union_layout,
} => { } => {
let tag_id_symbol = env.unique_symbol(); let tag_id_symbol = env.unique_symbol();
let mut tag_symbols = Vec::with_capacity_in(symbols.len() + 1, env.arena); let mut tag_symbols = Vec::with_capacity_in(symbols.len() + 1, env.arena);
tag_symbols.push(tag_id_symbol); tag_symbols.push(tag_id_symbol);
tag_symbols.extend(symbols); tag_symbols.extend(symbols);
let tag_layout = match lambda_set.runtime_representation() {
Layout::Union(inner) => inner,
_ => unreachable!(),
};
let expr1 = Expr::Literal(Literal::Int(tag_id as i128)); let expr1 = Expr::Literal(Literal::Int(tag_id as i128));
let expr2 = Expr::Tag { let expr2 = Expr::Tag {
tag_id, tag_id,
tag_layout, tag_layout: union_layout,
union_size, union_size,
tag_name, tag_name,
arguments: tag_symbols.into_bump_slice(), arguments: tag_symbols.into_bump_slice(),

View file

@ -200,6 +200,7 @@ pub enum ClosureRepresentation<'a> {
tag_name: TagName, tag_name: TagName,
tag_id: u8, tag_id: u8,
union_size: u8, union_size: u8,
union_layout: UnionLayout<'a>,
}, },
/// the representation is anything but a union /// the representation is anything but a union
Other(Layout<'a>), Other(Layout<'a>),
@ -241,6 +242,7 @@ impl<'a> LambdaSet<'a> {
tag_id: index as u8, tag_id: index as u8,
tag_layout: tags[index], tag_layout: tags[index],
tag_name: TagName::Closure(function_symbol), tag_name: TagName::Closure(function_symbol),
union_layout: *union,
} }
} }
UnionLayout::Recursive(_) => todo!("recursive closures"), UnionLayout::Recursive(_) => todo!("recursive closures"),

View file

@ -22,13 +22,13 @@ procedure Test.1 (Test.2, Test.3):
procedure Test.7 (Test.10, #Attr.12): procedure Test.7 (Test.10, #Attr.12):
let Test.4 = Index 1 #Attr.12; let Test.4 = CoerceToTagId (Id 0) (Index 1) #Attr.12;
let Test.29 = CallByName Num.24 Test.10 Test.4; let Test.29 = CallByName Num.24 Test.10 Test.4;
ret Test.29; ret Test.29;
procedure Test.8 (Test.11, #Attr.12): procedure Test.8 (Test.11, #Attr.12):
let Test.6 = Index 2 #Attr.12; let Test.6 = CoerceToTagId (Id 1) (Index 2) #Attr.12;
let Test.5 = Index 1 #Attr.12; let Test.5 = CoerceToTagId (Id 1) (Index 1) #Attr.12;
if Test.6 then if Test.6 then
let Test.24 = CallByName Num.26 Test.11 Test.5; let Test.24 = CallByName Num.26 Test.11 Test.5;
ret Test.24; ret Test.24;

View file

@ -7,12 +7,12 @@ procedure Num.26 (#Attr.2, #Attr.3):
ret Test.21; ret Test.21;
procedure Test.6 (Test.8, #Attr.12): procedure Test.6 (Test.8, #Attr.12):
let Test.4 = Index 1 #Attr.12; let Test.4 = CoerceToTagId (Id 0) (Index 1) #Attr.12;
let Test.25 = CallByName Num.24 Test.8 Test.4; let Test.25 = CallByName Num.24 Test.8 Test.4;
ret Test.25; ret Test.25;
procedure Test.7 (Test.9, #Attr.12): procedure Test.7 (Test.9, #Attr.12):
let Test.5 = Index 1 #Attr.12; let Test.5 = CoerceToTagId (Id 1) (Index 1) #Attr.12;
let Test.20 = CallByName Num.26 Test.9 Test.5; let Test.20 = CallByName Num.26 Test.9 Test.5;
ret Test.20; ret Test.20;