mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Merge pull request #4950 from roc-lang/keep-recptr-index
Initial support for linking recursive pointer layouts back to their source layouts
This commit is contained in:
commit
ad84e02abf
18 changed files with 639 additions and 132 deletions
|
@ -675,7 +675,7 @@ pub enum Layout<'a> {
|
|||
Boxed(InLayout<'a>),
|
||||
Union(UnionLayout<'a>),
|
||||
LambdaSet(LambdaSet<'a>),
|
||||
RecursivePointer,
|
||||
RecursivePointer(InLayout<'a>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
|
@ -880,7 +880,7 @@ impl<'a> UnionLayout<'a> {
|
|||
};
|
||||
|
||||
// TODO(recursive-layouts): simplify after we have disjoint recursive pointers
|
||||
if let Layout::RecursivePointer = interner.get(result) {
|
||||
if let Layout::RecursivePointer(_) = interner.get(result) {
|
||||
interner.insert(Layout::Union(self))
|
||||
} else {
|
||||
result
|
||||
|
@ -1523,7 +1523,7 @@ impl<'a> LambdaSet<'a> {
|
|||
let left = interner.get(*left);
|
||||
let right = interner.get(*right);
|
||||
|
||||
let left = if left == Layout::RecursivePointer {
|
||||
let left = if matches!(left, Layout::RecursivePointer(_)) {
|
||||
let runtime_repr = self.runtime_representation();
|
||||
debug_assert!(matches!(
|
||||
interner.get(runtime_repr),
|
||||
|
@ -1534,7 +1534,7 @@ impl<'a> LambdaSet<'a> {
|
|||
left
|
||||
};
|
||||
|
||||
let right = if right == Layout::RecursivePointer {
|
||||
let right = if matches!(right, Layout::RecursivePointer(_)) {
|
||||
let runtime_repr = self.runtime_representation();
|
||||
debug_assert!(matches!(
|
||||
interner.get(runtime_repr),
|
||||
|
@ -2259,8 +2259,11 @@ impl<'a, 'b> Env<'a, 'b> {
|
|||
) -> Cacheable<LayoutResult<'a>> {
|
||||
if self.is_seen(var) {
|
||||
// Always return recursion pointers directly, NEVER cache them as naked!
|
||||
// TODO(recursive-layouts): after we have disjoint recursive pointers, change this
|
||||
let rec_ptr = self.cache.put_in(Layout::RecursivePointer);
|
||||
// When this recursion pointer gets used in a recursive union, it will be filled to
|
||||
// looop back to the correct layout.
|
||||
// TODO(recursive-layouts): after the naked pointer is updated, we can cache `var` to
|
||||
// point to the updated layout.
|
||||
let rec_ptr = Layout::NAKED_RECURSIVE_PTR;
|
||||
return Cacheable(Ok(rec_ptr), NAKED_RECURSION_PTR);
|
||||
}
|
||||
|
||||
|
@ -2450,7 +2453,7 @@ impl<'a> Layout<'a> {
|
|||
LambdaSet(lambda_set) => interner
|
||||
.get(lambda_set.runtime_representation())
|
||||
.safe_to_memcpy(interner),
|
||||
Boxed(_) | RecursivePointer => {
|
||||
Boxed(_) | RecursivePointer(_) => {
|
||||
// We cannot memcpy pointers, because then we would have the same pointer in multiple places!
|
||||
false
|
||||
}
|
||||
|
@ -2536,7 +2539,7 @@ impl<'a> Layout<'a> {
|
|||
LambdaSet(lambda_set) => interner
|
||||
.get(lambda_set.runtime_representation())
|
||||
.stack_size_without_alignment(interner, target_info),
|
||||
RecursivePointer => target_info.ptr_width() as u32,
|
||||
RecursivePointer(_) => target_info.ptr_width() as u32,
|
||||
Boxed(_) => target_info.ptr_width() as u32,
|
||||
}
|
||||
}
|
||||
|
@ -2588,7 +2591,7 @@ impl<'a> Layout<'a> {
|
|||
.get(lambda_set.runtime_representation())
|
||||
.alignment_bytes(interner, target_info),
|
||||
Layout::Builtin(builtin) => builtin.alignment_bytes(target_info),
|
||||
Layout::RecursivePointer => target_info.ptr_width() as u32,
|
||||
Layout::RecursivePointer(_) => target_info.ptr_width() as u32,
|
||||
Layout::Boxed(_) => target_info.ptr_width() as u32,
|
||||
}
|
||||
}
|
||||
|
@ -2608,7 +2611,9 @@ impl<'a> Layout<'a> {
|
|||
Layout::LambdaSet(lambda_set) => interner
|
||||
.get(lambda_set.runtime_representation())
|
||||
.allocation_alignment_bytes(interner, target_info),
|
||||
Layout::RecursivePointer => unreachable!("should be looked up to get an actual layout"),
|
||||
Layout::RecursivePointer(_) => {
|
||||
unreachable!("should be looked up to get an actual layout")
|
||||
}
|
||||
Layout::Boxed(inner) => interner
|
||||
.get(*inner)
|
||||
.allocation_alignment_bytes(interner, target_info),
|
||||
|
@ -2653,7 +2658,7 @@ impl<'a> Layout<'a> {
|
|||
|
||||
Union(_) => true,
|
||||
|
||||
RecursivePointer => true,
|
||||
RecursivePointer(_) => true,
|
||||
|
||||
Builtin(List(_)) | Builtin(Str) => true,
|
||||
|
||||
|
@ -2692,7 +2697,7 @@ impl<'a> Layout<'a> {
|
|||
LambdaSet(lambda_set) => interner
|
||||
.get(lambda_set.runtime_representation())
|
||||
.contains_refcounted(interner),
|
||||
RecursivePointer => true,
|
||||
RecursivePointer(_) => true,
|
||||
Boxed(_) => true,
|
||||
}
|
||||
}
|
||||
|
@ -2727,7 +2732,7 @@ impl<'a> Layout<'a> {
|
|||
LambdaSet(lambda_set) => interner
|
||||
.get(lambda_set.runtime_representation())
|
||||
.to_doc(alloc, interner, parens),
|
||||
RecursivePointer => alloc.text("*self"),
|
||||
RecursivePointer(_) => alloc.text("*self"),
|
||||
Boxed(inner) => alloc
|
||||
.text("Boxed(")
|
||||
.append(interner.get(inner).to_doc(alloc, interner, parens))
|
||||
|
@ -3110,8 +3115,9 @@ fn layout_from_flat_type<'a>(
|
|||
}
|
||||
Func(args, closure_var, ret_var) => {
|
||||
if env.is_seen(closure_var) {
|
||||
// TODO(recursive-layouts): change after disjoint recursive layouts supported
|
||||
let rec_ptr = env.cache.put_in(Layout::RecursivePointer);
|
||||
// TODO(recursive-layouts): after the naked pointer is updated, we can cache `var` to
|
||||
// point to the updated layout.
|
||||
let rec_ptr = Layout::NAKED_RECURSIVE_PTR;
|
||||
Cacheable(Ok(rec_ptr), NAKED_RECURSION_PTR)
|
||||
} else {
|
||||
let mut criteria = CACHEABLE;
|
||||
|
@ -3801,8 +3807,7 @@ where
|
|||
&& is_recursive_tag_union(&layout);
|
||||
|
||||
let arg_layout = if self_recursion {
|
||||
// TODO(recursive-layouts): fix after disjoint recursive pointers supported
|
||||
env.cache.put_in(Layout::RecursivePointer)
|
||||
Layout::NAKED_RECURSIVE_PTR
|
||||
} else {
|
||||
in_layout
|
||||
};
|
||||
|
@ -4067,7 +4072,9 @@ where
|
|||
for &var in variables {
|
||||
// TODO does this cause problems with mutually recursive unions?
|
||||
if rec_var == subs.get_root_key_without_compacting(var) {
|
||||
tag_layout.push(env.cache.put_in(Layout::RecursivePointer));
|
||||
// The naked pointer will get fixed-up to loopback to the union below when we
|
||||
// intern the union.
|
||||
tag_layout.push(Layout::NAKED_RECURSIVE_PTR);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -4110,7 +4117,10 @@ where
|
|||
};
|
||||
criteria.pass_through_recursive_union(rec_var);
|
||||
|
||||
let union_layout = env.cache.put_in(Layout::Union(union_layout));
|
||||
let union_layout = env
|
||||
.cache
|
||||
.interner
|
||||
.insert_recursive(env.arena, Layout::Union(union_layout));
|
||||
|
||||
Cacheable(Ok(union_layout), criteria)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue