Wrap layouts in a LayoutRepr constructor

Part 1 of support semantic layout representations.
This commit is contained in:
Ayaz Hafiz 2023-05-10 13:22:10 -05:00
parent c2d2bd4bb9
commit c3eeb5e2cc
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
32 changed files with 1254 additions and 1021 deletions

View file

@ -12,6 +12,8 @@ use roc_collections::{default_hasher, BumpMap};
use roc_module::symbol::Symbol;
use roc_target::TargetInfo;
use crate::layout::LayoutRepr;
use super::{Builtin, FieldOrderHash, LambdaSet, Layout, SeenRecPtrs, UnionLayout};
macro_rules! cache_interned_layouts {
@ -48,23 +50,23 @@ macro_rules! cache_interned_layouts {
cache_interned_layouts! {
0, VOID, pub, Layout::VOID_NAKED
1, UNIT, pub, Layout::UNIT_NAKED
2, BOOL, pub, Layout::Builtin(Builtin::Bool)
3, U8, pub, Layout::Builtin(Builtin::Int(IntWidth::U8))
4, U16, pub, Layout::Builtin(Builtin::Int(IntWidth::U16))
5, U32, pub, Layout::Builtin(Builtin::Int(IntWidth::U32))
6, U64, pub, Layout::Builtin(Builtin::Int(IntWidth::U64))
7, U128, pub, Layout::Builtin(Builtin::Int(IntWidth::U128))
8, I8, pub, Layout::Builtin(Builtin::Int(IntWidth::I8))
9, I16, pub, Layout::Builtin(Builtin::Int(IntWidth::I16))
10, I32, pub, Layout::Builtin(Builtin::Int(IntWidth::I32))
11, I64, pub, Layout::Builtin(Builtin::Int(IntWidth::I64))
12, I128, pub, Layout::Builtin(Builtin::Int(IntWidth::I128))
13, F32, pub, Layout::Builtin(Builtin::Float(FloatWidth::F32))
14, F64, pub, Layout::Builtin(Builtin::Float(FloatWidth::F64))
15, DEC, pub, Layout::Builtin(Builtin::Decimal)
16, STR, pub, Layout::Builtin(Builtin::Str)
17, OPAQUE_PTR, pub, Layout::Boxed(Layout::VOID)
18, NAKED_RECURSIVE_PTR, pub(super), Layout::RecursivePointer(Layout::VOID)
2, BOOL, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Bool) }
3, U8, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U8)) }
4, U16, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U16)) }
5, U32, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U32)) }
6, U64, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U64)) }
7, U128, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U128)) }
8, I8, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::I8)) }
9, I16, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::I16)) }
10, I32, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::I32)) }
11, I64, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::I64)) }
12, I128, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::I128)) }
13, F32, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) }
14, F64, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) }
15, DEC, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Decimal) }
16, STR, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Str) }
17, OPAQUE_PTR, pub, Layout{ repr: LayoutRepr::Boxed(Layout::VOID) }
18, NAKED_RECURSIVE_PTR, pub(super), Layout{ repr: LayoutRepr::RecursivePointer(Layout::VOID) }
; 19
}
@ -107,10 +109,14 @@ impl_to_from_int_width! {
}
impl<'a> Layout<'a> {
pub(super) const VOID_NAKED: Self = Layout::Union(UnionLayout::NonRecursive(&[]));
pub(super) const UNIT_NAKED: Self = Layout::Struct {
field_layouts: &[],
field_order_hash: FieldOrderHash::ZERO_FIELD_HASH,
pub(super) const VOID_NAKED: Self = Layout {
repr: LayoutRepr::Union(UnionLayout::NonRecursive(&[])),
};
pub(super) const UNIT_NAKED: Self = Layout {
repr: LayoutRepr::Struct {
field_layouts: &[],
field_order_hash: FieldOrderHash::ZERO_FIELD_HASH,
},
};
pub const fn float_width(w: FloatWidth) -> InLayout<'static> {
@ -138,7 +144,7 @@ pub trait LayoutInterner<'a>: Sized {
// allocations when values already have interned representations.
fn insert(&mut self, value: Layout<'a>) -> InLayout<'a>;
/// Creates a [LambdaSet], including caching the [Layout::LambdaSet] representation of the
/// Creates a [LambdaSet], including caching the [LayoutRepr::LambdaSet] representation of the
/// lambda set onto itself.
fn insert_lambda_set(
&mut self,
@ -209,17 +215,18 @@ pub trait LayoutInterner<'a>: Sized {
fn chase_recursive(&self, mut layout: InLayout<'a>) -> Layout<'a> {
loop {
match self.get(layout) {
Layout::RecursivePointer(l) => layout = l,
other => return other,
let lay = self.get(layout);
match lay.repr {
LayoutRepr::RecursivePointer(l) => layout = l,
_ => return lay,
}
}
}
fn chase_recursive_in(&self, mut layout: InLayout<'a>) -> InLayout<'a> {
loop {
match self.get(layout) {
Layout::RecursivePointer(l) => layout = l,
match self.get(layout).repr {
LayoutRepr::RecursivePointer(l) => layout = l,
_ => return layout,
}
}
@ -271,9 +278,9 @@ pub trait LayoutInterner<'a>: Sized {
D::Doc: Clone,
A: Clone,
{
use Layout::*;
use LayoutRepr::*;
match self.get(layout) {
match self.get(layout).repr {
Builtin(builtin) => builtin.to_doc(alloc, self, seen_rec, parens),
Struct { field_layouts, .. } => {
let fields_doc = field_layouts
@ -353,7 +360,7 @@ pub trait LayoutInterner<'a>: Sized {
///
/// ```ignore(illustrative)
/// fn is_rec_ptr<'a>(interner: &impl LayoutInterner<'a>, layout: InLayout<'a>) -> bool {
/// if matches!(interner.get(layout), Layout::RecursivePointer(..)) {
/// if matches!(interner.get(layout), LayoutRepr::RecursivePointer(..)) {
/// return true;
/// }
///
@ -639,7 +646,9 @@ impl<'a> GlobalLayoutInterner<'a> {
set,
..normalized
};
let lambda_set_layout = Layout::LambdaSet(full_lambda_set);
let lambda_set_layout = Layout {
repr: LayoutRepr::LambdaSet(full_lambda_set),
};
vec[slot.0] = lambda_set_layout;
@ -945,9 +954,9 @@ macro_rules! st_impl {
representation,
full_layout: slot,
};
self.vec[slot.0] = Layout::LambdaSet(lambda_set);
self.vec[slot.0] = Layout { repr: LayoutRepr::LambdaSet(lambda_set) };
let _old = self.map.insert(Layout::LambdaSet(lambda_set), slot);
let _old = self.map.insert(Layout { repr: LayoutRepr::LambdaSet(lambda_set) }, slot);
debug_assert!(_old.is_none());
let _old = self.normalized_lambda_set_map
@ -1003,7 +1012,7 @@ mod reify {
use bumpalo::{collections::Vec, Bump};
use roc_module::symbol::Symbol;
use crate::layout::{Builtin, LambdaSet, Layout, UnionLayout};
use crate::layout::{Builtin, LambdaSet, Layout, LayoutRepr, UnionLayout};
use super::{InLayout, LayoutInterner, NeedsRecursionPointerFixup};
@ -1014,26 +1023,29 @@ mod reify {
slot: InLayout<'a>,
normalized_layout: Layout<'a>,
) -> Layout<'a> {
match normalized_layout {
Layout::Builtin(builtin) => {
Layout::Builtin(reify_builtin(arena, interner, slot, builtin))
let repr = match normalized_layout.repr {
LayoutRepr::Builtin(builtin) => {
LayoutRepr::Builtin(reify_builtin(arena, interner, slot, builtin))
}
Layout::Struct {
LayoutRepr::Struct {
field_order_hash,
field_layouts,
} => Layout::Struct {
} => LayoutRepr::Struct {
field_order_hash,
field_layouts: reify_layout_slice(arena, interner, slot, field_layouts),
},
Layout::Boxed(lay) => Layout::Boxed(reify_layout(arena, interner, slot, lay)),
Layout::Union(un) => Layout::Union(reify_union(arena, interner, slot, un)),
Layout::LambdaSet(ls) => Layout::LambdaSet(reify_lambda_set(arena, interner, slot, ls)),
Layout::RecursivePointer(l) => {
LayoutRepr::Boxed(lay) => LayoutRepr::Boxed(reify_layout(arena, interner, slot, lay)),
LayoutRepr::Union(un) => LayoutRepr::Union(reify_union(arena, interner, slot, un)),
LayoutRepr::LambdaSet(ls) => {
LayoutRepr::LambdaSet(reify_lambda_set(arena, interner, slot, ls))
}
LayoutRepr::RecursivePointer(l) => {
// If the layout is not void at its point then it has already been solved as
// another recursive union's layout, do not change it.
Layout::RecursivePointer(if l == Layout::VOID { slot } else { l })
LayoutRepr::RecursivePointer(if l == Layout::VOID { slot } else { l })
}
}
};
Layout { repr }
}
fn reify_layout<'a>(
@ -1173,7 +1185,7 @@ mod reify {
}
mod equiv {
use crate::layout::{self, Layout, UnionLayout};
use crate::layout::{self, LayoutRepr, UnionLayout};
use super::{InLayout, LayoutInterner};
@ -1209,8 +1221,8 @@ mod equiv {
if l1 == l2 {
continue;
}
use Layout::*;
match (interner.get(l1), interner.get(l2)) {
use LayoutRepr::*;
match (interner.get(l1).repr, interner.get(l2).repr) {
(RecursivePointer(rec), _) => stack.push((rec, l2)),
(_, RecursivePointer(rec)) => stack.push((l1, rec)),
(Builtin(b1), Builtin(b2)) => {
@ -1318,7 +1330,7 @@ mod equiv {
pub mod dbg {
use roc_module::symbol::Symbol;
use crate::layout::{Builtin, LambdaSet, Layout, UnionLayout};
use crate::layout::{Builtin, LambdaSet, LayoutRepr, UnionLayout};
use super::{InLayout, LayoutInterner};
@ -1326,12 +1338,12 @@ pub mod dbg {
impl<'a, 'r, I: LayoutInterner<'a>> std::fmt::Debug for Dbg<'a, 'r, I> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.0.get(self.1) {
Layout::Builtin(b) => f
match self.0.get(self.1).repr {
LayoutRepr::Builtin(b) => f
.debug_tuple("Builtin")
.field(&DbgBuiltin(self.0, b))
.finish(),
Layout::Struct {
LayoutRepr::Struct {
field_order_hash,
field_layouts,
} => f
@ -1339,13 +1351,15 @@ pub mod dbg {
.field("hash", &field_order_hash)
.field("fields", &DbgFields(self.0, field_layouts))
.finish(),
Layout::Boxed(b) => f.debug_tuple("Boxed").field(&Dbg(self.0, b)).finish(),
Layout::Union(un) => f.debug_tuple("Union").field(&DbgUnion(self.0, un)).finish(),
Layout::LambdaSet(ls) => f
LayoutRepr::Boxed(b) => f.debug_tuple("Boxed").field(&Dbg(self.0, b)).finish(),
LayoutRepr::Union(un) => {
f.debug_tuple("Union").field(&DbgUnion(self.0, un)).finish()
}
LayoutRepr::LambdaSet(ls) => f
.debug_tuple("LambdaSet")
.field(&DbgLambdaSet(self.0, ls))
.finish(),
Layout::RecursivePointer(rp) => {
LayoutRepr::RecursivePointer(rp) => {
f.debug_tuple("RecursivePointer").field(&rp.0).finish()
}
}
@ -1467,7 +1481,7 @@ mod insert_lambda_set {
use roc_module::symbol::Symbol;
use roc_target::TargetInfo;
use crate::layout::{LambdaSet, Layout};
use crate::layout::{LambdaSet, Layout, LayoutRepr};
use super::{GlobalLayoutInterner, InLayout, LayoutInterner, NeedsRecursionPointerFixup};
@ -1509,7 +1523,9 @@ mod insert_lambda_set {
let lambda_set =
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, TEST_SET, FIXUP, Layout::UNIT);
let lambda_set_layout_in = interner.insert(Layout::LambdaSet(lambda_set));
let lambda_set_layout_in = interner.insert(Layout {
repr: LayoutRepr::LambdaSet(lambda_set),
});
assert_eq!(lambda_set.full_layout, lambda_set_layout_in);
}
@ -1558,35 +1574,37 @@ mod insert_recursive_layout {
use bumpalo::Bump;
use roc_target::TargetInfo;
use crate::layout::{Builtin, InLayout, Layout, UnionLayout};
use crate::layout::{Builtin, InLayout, Layout, LayoutRepr, UnionLayout};
use super::{GlobalLayoutInterner, LayoutInterner};
const TARGET_INFO: TargetInfo = TargetInfo::default_x86_64();
fn make_layout<'a>(arena: &'a Bump, interner: &mut impl LayoutInterner<'a>) -> Layout<'a> {
Layout::Union(UnionLayout::Recursive(&*arena.alloc([
&*arena.alloc([
interner.insert(Layout::Builtin(Builtin::List(Layout::NAKED_RECURSIVE_PTR))),
]),
let list_rec = Layout {
repr: LayoutRepr::Builtin(Builtin::List(Layout::NAKED_RECURSIVE_PTR)),
};
let repr = LayoutRepr::Union(UnionLayout::Recursive(&*arena.alloc([
&*arena.alloc([interner.insert(list_rec)]),
&*arena.alloc_slice_fill_iter([interner.insert(Layout::struct_no_name_order(
&*arena.alloc([Layout::NAKED_RECURSIVE_PTR]),
))]),
])))
])));
Layout { repr }
}
fn get_rec_ptr_index<'a>(interner: &impl LayoutInterner<'a>, layout: InLayout<'a>) -> usize {
match interner.chase_recursive(layout) {
Layout::Union(UnionLayout::Recursive(&[&[l1], &[l2]])) => {
match (interner.get(l1), interner.get(l2)) {
match interner.chase_recursive(layout).repr {
LayoutRepr::Union(UnionLayout::Recursive(&[&[l1], &[l2]])) => {
match (interner.get(l1).repr, interner.get(l2).repr) {
(
Layout::Builtin(Builtin::List(l1)),
Layout::Struct {
LayoutRepr::Builtin(Builtin::List(l1)),
LayoutRepr::Struct {
field_order_hash: _,
field_layouts: &[l2],
},
) => match (interner.get(l1), interner.get(l2)) {
(Layout::RecursivePointer(i1), Layout::RecursivePointer(i2)) => {
) => match (interner.get(l1).repr, interner.get(l2).repr) {
(LayoutRepr::RecursivePointer(i1), LayoutRepr::RecursivePointer(i2)) => {
assert_eq!(i1, i2);
assert_ne!(i1, Layout::VOID);
i1.0