mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-14 07:29:02 +03:00
Support box/unbox for types that are typically only on the stack
Closes #2786
This commit is contained in:
parent
ebb03f60dd
commit
a102a7497e
@ -468,7 +468,7 @@ impl<'a> UnionLayout<'a> {
|
|||||||
|
|
||||||
pub fn allocation_alignment_bytes(&self, target_info: TargetInfo) -> u32 {
|
pub fn allocation_alignment_bytes(&self, target_info: TargetInfo) -> u32 {
|
||||||
let allocation = match self {
|
let allocation = match self {
|
||||||
UnionLayout::NonRecursive(_) => unreachable!("not heap-allocated"),
|
UnionLayout::NonRecursive(tags) => Self::tags_alignment_bytes(tags, target_info),
|
||||||
UnionLayout::Recursive(tags) => Self::tags_alignment_bytes(tags, target_info),
|
UnionLayout::Recursive(tags) => Self::tags_alignment_bytes(tags, target_info),
|
||||||
UnionLayout::NonNullableUnwrapped(field_layouts) => {
|
UnionLayout::NonNullableUnwrapped(field_layouts) => {
|
||||||
Layout::struct_no_name_order(field_layouts).alignment_bytes(target_info)
|
Layout::struct_no_name_order(field_layouts).alignment_bytes(target_info)
|
||||||
@ -1150,9 +1150,11 @@ impl<'a> Layout<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocation_alignment_bytes(&self, target_info: TargetInfo) -> u32 {
|
pub fn allocation_alignment_bytes(&self, target_info: TargetInfo) -> u32 {
|
||||||
|
let ptr_width = target_info.ptr_width() as u32;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Layout::Builtin(builtin) => builtin.allocation_alignment_bytes(target_info),
|
Layout::Builtin(builtin) => builtin.allocation_alignment_bytes(target_info),
|
||||||
Layout::Struct { .. } => unreachable!("not heap-allocated"),
|
Layout::Struct { .. } => self.alignment_bytes(target_info).max(ptr_width),
|
||||||
Layout::Union(union_layout) => union_layout.allocation_alignment_bytes(target_info),
|
Layout::Union(union_layout) => union_layout.allocation_alignment_bytes(target_info),
|
||||||
Layout::LambdaSet(lambda_set) => lambda_set
|
Layout::LambdaSet(lambda_set) => lambda_set
|
||||||
.runtime_representation()
|
.runtime_representation()
|
||||||
@ -1545,9 +1547,6 @@ impl<'a> Builtin<'a> {
|
|||||||
let ptr_width = target_info.ptr_width() as u32;
|
let ptr_width = target_info.ptr_width() as u32;
|
||||||
|
|
||||||
let allocation = match self {
|
let allocation = match self {
|
||||||
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal => {
|
|
||||||
unreachable!("not heap-allocated")
|
|
||||||
}
|
|
||||||
Builtin::Str => ptr_width,
|
Builtin::Str => ptr_width,
|
||||||
Builtin::Dict(k, v) => k
|
Builtin::Dict(k, v) => k
|
||||||
.alignment_bytes(target_info)
|
.alignment_bytes(target_info)
|
||||||
@ -1555,6 +1554,11 @@ impl<'a> Builtin<'a> {
|
|||||||
.max(ptr_width),
|
.max(ptr_width),
|
||||||
Builtin::Set(k) => k.alignment_bytes(target_info).max(ptr_width),
|
Builtin::Set(k) => k.alignment_bytes(target_info).max(ptr_width),
|
||||||
Builtin::List(e) => e.alignment_bytes(target_info).max(ptr_width),
|
Builtin::List(e) => e.alignment_bytes(target_info).max(ptr_width),
|
||||||
|
// The following are usually not heap-allocated, but they might be when inside a Box.
|
||||||
|
Builtin::Int(int_width) => int_width.alignment_bytes(target_info).max(ptr_width),
|
||||||
|
Builtin::Float(float_width) => float_width.alignment_bytes(target_info).max(ptr_width),
|
||||||
|
Builtin::Bool => (core::mem::align_of::<bool>() as u32).max(ptr_width),
|
||||||
|
Builtin::Decimal => IntWidth::I128.alignment_bytes(target_info).max(ptr_width),
|
||||||
};
|
};
|
||||||
|
|
||||||
allocation.max(ptr_width)
|
allocation.max(ptr_width)
|
||||||
|
@ -3275,3 +3275,47 @@ fn box_and_unbox_string() {
|
|||||||
RocStr
|
RocStr
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
|
fn box_and_unbox_num() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Box.unbox (Box.box (123u8))
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
123,
|
||||||
|
u8
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
|
fn box_and_unbox_record() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
Box.unbox (Box.box { a: 15u8, b: 27u8 })
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
(15, 27),
|
||||||
|
(u8, u8)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(any(feature = "gen-llvm"))]
|
||||||
|
fn box_and_unbox_tag_union() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
v : [ A U8, B U8 ] # usually stack allocated
|
||||||
|
v = B 27u8
|
||||||
|
Box.unbox (Box.box v)
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
(27, 1),
|
||||||
|
(u8, u8)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user