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

@ -18,8 +18,8 @@ use roc_mono::ir::{
Literal, ModifyRc, OptLevel, Proc, ProcLayout, SingleEntryPoint, Stmt,
};
use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutInterner, Niche, RawFunctionLayout, STLayoutInterner,
UnionLayout,
Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, Niche, RawFunctionLayout,
STLayoutInterner, UnionLayout,
};
// just using one module for now
@ -852,8 +852,9 @@ fn call_spec<'a>(
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
let state_layout =
interner.insert(Layout::Builtin(Builtin::List(*return_layout)));
let state_layout = interner.insert(Layout {
repr: LayoutRepr::Builtin(Builtin::List(*return_layout)),
});
let state_type = layout_spec(env, builder, interner, state_layout)?;
let init_state = new_list(builder, block, output_element_type)?;
@ -880,7 +881,9 @@ fn call_spec<'a>(
let arg0_layout = argument_layouts[0];
let state_layout = interner.insert(Layout::Builtin(Builtin::List(arg0_layout)));
let state_layout = interner.insert(Layout {
repr: LayoutRepr::Builtin(Builtin::List(arg0_layout)),
});
let state_type = layout_spec(env, builder, interner, state_layout)?;
let init_state = list;
@ -907,8 +910,9 @@ fn call_spec<'a>(
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
let state_layout =
interner.insert(Layout::Builtin(Builtin::List(*return_layout)));
let state_layout = interner.insert(Layout {
repr: LayoutRepr::Builtin(Builtin::List(*return_layout)),
});
let state_type = layout_spec(env, builder, interner, state_layout)?;
let init_state = new_list(builder, block, output_element_type)?;
@ -941,8 +945,9 @@ fn call_spec<'a>(
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
let state_layout =
interner.insert(Layout::Builtin(Builtin::List(*return_layout)));
let state_layout = interner.insert(Layout {
repr: LayoutRepr::Builtin(Builtin::List(*return_layout)),
});
let state_type = layout_spec(env, builder, interner, state_layout)?;
let init_state = new_list(builder, block, output_element_type)?;
@ -981,8 +986,9 @@ fn call_spec<'a>(
let output_element_type = layout_spec(env, builder, interner, *return_layout)?;
let state_layout =
interner.insert(Layout::Builtin(Builtin::List(*return_layout)));
let state_layout = interner.insert(Layout {
repr: LayoutRepr::Builtin(Builtin::List(*return_layout)),
});
let state_type = layout_spec(env, builder, interner, state_layout)?;
let init_state = new_list(builder, block, output_element_type)?;
@ -1111,21 +1117,21 @@ fn lowlevel_spec<'a>(
let new_list = with_new_heap_cell(builder, block, bag)?;
// depending on the types, the list or value will come first in the struct
let fields = match interner.get(layout) {
Layout::Struct { field_layouts, .. } => field_layouts,
let fields = match interner.get(layout).repr {
LayoutRepr::Struct { field_layouts, .. } => field_layouts,
_ => unreachable!(),
};
match (interner.get(fields[0]), interner.get(fields[1])) {
(Layout::Builtin(Builtin::List(_)), Layout::Builtin(Builtin::List(_))) => {
match (interner.get(fields[0]).repr, interner.get(fields[1]).repr) {
(LayoutRepr::Builtin(Builtin::List(_)), LayoutRepr::Builtin(Builtin::List(_))) => {
// field name is the tie breaker, list is first in
// { list : List a, value : a }
builder.add_make_tuple(block, &[new_list, old_value])
}
(Layout::Builtin(Builtin::List(_)), _) => {
(LayoutRepr::Builtin(Builtin::List(_)), _) => {
builder.add_make_tuple(block, &[new_list, old_value])
}
(_, Layout::Builtin(Builtin::List(_))) => {
(_, LayoutRepr::Builtin(Builtin::List(_))) => {
builder.add_make_tuple(block, &[old_value, new_list])
}
_ => unreachable!(),
@ -1144,8 +1150,8 @@ fn lowlevel_spec<'a>(
ListWithCapacity => {
// essentially an empty list, capacity is not relevant for morphic
match interner.get(layout) {
Layout::Builtin(Builtin::List(element_layout)) => {
match interner.get(layout).repr {
LayoutRepr::Builtin(Builtin::List(element_layout)) => {
let type_id = layout_spec(env, builder, interner, element_layout)?;
new_list(builder, block, type_id)
}
@ -1440,8 +1446,8 @@ fn expr_spec<'a>(
}
}
EmptyArray => match interner.get(layout) {
Layout::Builtin(Builtin::List(element_layout)) => {
EmptyArray => match interner.get(layout).repr {
LayoutRepr::Builtin(Builtin::List(element_layout)) => {
let type_id = layout_spec(env, builder, interner, element_layout)?;
new_list(builder, block, type_id)
}
@ -1457,8 +1463,8 @@ fn expr_spec<'a>(
} => {
let tag_value_id = env.symbols[symbol];
let union_layout = match interner.get(layout) {
Layout::Union(ul) => ul,
let union_layout = match interner.get(layout).repr {
LayoutRepr::Union(ul) => ul,
_ => unreachable!(),
};
@ -1537,9 +1543,9 @@ fn layout_spec_help<'a>(
interner: &STLayoutInterner<'a>,
layout: InLayout<'a>,
) -> Result<TypeId> {
use Layout::*;
use LayoutRepr::*;
match interner.get(layout) {
match interner.get(layout).repr {
Builtin(builtin) => builtin_spec(env, builder, interner, &builtin),
Struct { field_layouts, .. } => {
build_recursive_tuple_type(env, builder, interner, field_layouts)
@ -1580,8 +1586,8 @@ fn layout_spec_help<'a>(
builder.add_tuple_type(&[cell_type, inner_type])
}
// TODO(recursive-layouts): update once we have recursive pointer loops
RecursivePointer(union_layout) => match interner.get(union_layout) {
Layout::Union(union_layout) => {
RecursivePointer(union_layout) => match interner.get(union_layout).repr {
LayoutRepr::Union(union_layout) => {
assert!(!matches!(union_layout, UnionLayout::NonRecursive(..)));
let type_name_bytes = recursive_tag_union_name_bytes(&union_layout).as_bytes();
let type_name = TypeName(&type_name_bytes);

View file

@ -13,8 +13,8 @@ use roc_mono::ir::{
SelfRecursive, Stmt,
};
use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, TagIdIntType,
UnionLayout,
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, LayoutRepr, STLayoutInterner,
TagIdIntType, UnionLayout,
};
use roc_mono::low_level::HigherOrder;
use roc_target::TargetInfo;
@ -906,12 +906,12 @@ impl<
other => {
//
match self.layout_interner.get(other) {
Layout::Boxed(_) => {
match self.layout_interner.get(other).repr {
LayoutRepr::Boxed(_) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
ASM::mov_reg64_reg64(&mut self.buf, dst_reg, CC::GENERAL_RETURN_REGS[0]);
}
Layout::LambdaSet(lambda_set) => {
LayoutRepr::LambdaSet(lambda_set) => {
self.move_return_value(dst, &lambda_set.runtime_representation())
}
_ => {
@ -1064,13 +1064,13 @@ impl<
}
fn build_num_abs(&mut self, dst: &Symbol, src: &Symbol, layout: &InLayout<'a>) {
match self.interner().get(*layout) {
Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
match self.interner().get(*layout).repr {
LayoutRepr::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src_reg = self.storage_manager.load_to_general_reg(&mut self.buf, src);
ASM::abs_reg64_reg64(&mut self.buf, dst_reg, src_reg);
}
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
let src_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src);
ASM::abs_freg64_freg64(&mut self.buf, &mut self.relocs, dst_reg, src_reg);
@ -1080,8 +1080,8 @@ impl<
}
fn build_num_add(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
match self.layout_interner.get(*layout) {
Layout::Builtin(Builtin::Int(quadword_and_smaller!())) => {
match self.layout_interner.get(*layout).repr {
LayoutRepr::Builtin(Builtin::Int(quadword_and_smaller!())) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self
.storage_manager
@ -1091,13 +1091,13 @@ impl<
.load_to_general_reg(&mut self.buf, src2);
ASM::add_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
}
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
ASM::add_freg64_freg64_freg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
}
Layout::Builtin(Builtin::Float(FloatWidth::F32)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
@ -1123,8 +1123,10 @@ impl<
let base_offset = self.storage_manager.claim_stack_area(dst, struct_size);
match self.layout_interner.get(*num_layout) {
Layout::Builtin(Int(IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8)) => {
match self.layout_interner.get(*num_layout).repr {
LayoutRepr::Builtin(Int(
IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8,
)) => {
let dst_reg = self
.storage_manager
.claim_general_reg(buf, &Symbol::DEV_TMP);
@ -1145,13 +1147,15 @@ impl<
self.free_symbol(&Symbol::DEV_TMP);
self.free_symbol(&Symbol::DEV_TMP2);
}
Layout::Builtin(Int(IntWidth::U64 | IntWidth::U32 | IntWidth::U16 | IntWidth::U8)) => {
LayoutRepr::Builtin(Int(
IntWidth::U64 | IntWidth::U32 | IntWidth::U16 | IntWidth::U8,
)) => {
todo!("addChecked for unsigned integers")
}
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
todo!("addChecked for f64")
}
Layout::Builtin(Builtin::Float(FloatWidth::F32)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
todo!("addChecked for f32")
}
x => todo!("NumAdd: layout, {:?}", x),
@ -1166,10 +1170,10 @@ impl<
num_layout: &InLayout<'a>,
return_layout: &InLayout<'a>,
) {
let function_name = match self.interner().get(*num_layout) {
Layout::Builtin(Builtin::Int(width)) => &bitcode::NUM_SUB_CHECKED_INT[width],
Layout::Builtin(Builtin::Float(width)) => &bitcode::NUM_SUB_CHECKED_FLOAT[width],
Layout::Builtin(Builtin::Decimal) => bitcode::DEC_SUB_WITH_OVERFLOW,
let function_name = match self.interner().get(*num_layout).repr {
LayoutRepr::Builtin(Builtin::Int(width)) => &bitcode::NUM_SUB_CHECKED_INT[width],
LayoutRepr::Builtin(Builtin::Float(width)) => &bitcode::NUM_SUB_CHECKED_FLOAT[width],
LayoutRepr::Builtin(Builtin::Decimal) => bitcode::DEC_SUB_WITH_OVERFLOW,
x => internal_error!("NumSubChecked is not defined for {:?}", x),
};
@ -1185,8 +1189,10 @@ impl<
fn build_num_mul(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
use Builtin::Int;
match self.layout_interner.get(*layout) {
Layout::Builtin(Int(IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8)) => {
match self.layout_interner.get(*layout).repr {
LayoutRepr::Builtin(Int(
IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8,
)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self
.storage_manager
@ -1196,7 +1202,9 @@ impl<
.load_to_general_reg(&mut self.buf, src2);
ASM::imul_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
}
Layout::Builtin(Int(IntWidth::U64 | IntWidth::U32 | IntWidth::U16 | IntWidth::U8)) => {
LayoutRepr::Builtin(Int(
IntWidth::U64 | IntWidth::U32 | IntWidth::U16 | IntWidth::U8,
)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self
.storage_manager
@ -1213,7 +1221,7 @@ impl<
src2_reg,
);
}
Layout::Builtin(Builtin::Int(IntWidth::I128 | IntWidth::U128)) => {
LayoutRepr::Builtin(Builtin::Int(IntWidth::I128 | IntWidth::U128)) => {
let int_width = match *layout {
Layout::I128 => IntWidth::I128,
Layout::U128 => IntWidth::U128,
@ -1228,13 +1236,13 @@ impl<
layout,
);
}
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
ASM::mul_freg64_freg64_freg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
}
Layout::Builtin(Builtin::Float(FloatWidth::F32)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
@ -1245,8 +1253,8 @@ impl<
}
fn build_num_div(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
match self.layout_interner.get(*layout) {
Layout::Builtin(Builtin::Int(
match self.layout_interner.get(*layout).repr {
LayoutRepr::Builtin(Builtin::Int(
IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8,
)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
@ -1265,7 +1273,7 @@ impl<
src2_reg,
);
}
Layout::Builtin(Builtin::Int(
LayoutRepr::Builtin(Builtin::Int(
IntWidth::U64 | IntWidth::U32 | IntWidth::U16 | IntWidth::U8,
)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
@ -1284,13 +1292,13 @@ impl<
src2_reg,
);
}
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
ASM::div_freg64_freg64_freg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
}
Layout::Builtin(Builtin::Float(FloatWidth::F32)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
@ -1301,8 +1309,8 @@ impl<
}
fn build_num_rem(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>) {
match self.layout_interner.get(*layout) {
Layout::Builtin(Builtin::Int(
match self.layout_interner.get(*layout).repr {
LayoutRepr::Builtin(Builtin::Int(
IntWidth::I64 | IntWidth::I32 | IntWidth::I16 | IntWidth::I8,
)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
@ -1321,7 +1329,7 @@ impl<
src2_reg,
);
}
Layout::Builtin(Builtin::Int(
LayoutRepr::Builtin(Builtin::Int(
IntWidth::U64 | IntWidth::U32 | IntWidth::U16 | IntWidth::U8,
)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
@ -1345,8 +1353,8 @@ impl<
}
fn build_num_neg(&mut self, dst: &Symbol, src: &Symbol, layout: &InLayout<'a>) {
match self.layout_interner.get(*layout) {
Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
match self.layout_interner.get(*layout).repr {
LayoutRepr::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src_reg = self.storage_manager.load_to_general_reg(&mut self.buf, src);
ASM::neg_reg64_reg64(&mut self.buf, dst_reg, src_reg);
@ -1368,8 +1376,8 @@ impl<
src2: &Symbol,
layout: &InLayout<'a>,
) {
match self.layout_interner.get(*layout) {
Layout::Builtin(Builtin::Int(quadword_and_smaller!())) => {
match self.layout_interner.get(*layout).repr {
LayoutRepr::Builtin(Builtin::Int(quadword_and_smaller!())) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self
.storage_manager
@ -1560,47 +1568,47 @@ impl<
) {
let dst_reg = self.storage_manager.claim_float_reg(&mut self.buf, dst);
match (
self.layout_interner.get(*arg_layout),
self.layout_interner.get(*ret_layout),
self.layout_interner.get(*arg_layout).repr,
self.layout_interner.get(*ret_layout).repr,
) {
(
Layout::Builtin(Builtin::Int(IntWidth::I32 | IntWidth::I64)),
Layout::Builtin(Builtin::Float(FloatWidth::F64)),
LayoutRepr::Builtin(Builtin::Int(IntWidth::I32 | IntWidth::I64)),
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)),
) => {
let src_reg = self.storage_manager.load_to_general_reg(&mut self.buf, src);
ASM::to_float_freg64_reg64(&mut self.buf, dst_reg, src_reg);
}
(
Layout::Builtin(Builtin::Int(IntWidth::I32 | IntWidth::I64)),
Layout::Builtin(Builtin::Float(FloatWidth::F32)),
LayoutRepr::Builtin(Builtin::Int(IntWidth::I32 | IntWidth::I64)),
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)),
) => {
let src_reg = self.storage_manager.load_to_general_reg(&mut self.buf, src);
ASM::to_float_freg32_reg64(&mut self.buf, dst_reg, src_reg);
}
(
Layout::Builtin(Builtin::Float(FloatWidth::F64)),
Layout::Builtin(Builtin::Float(FloatWidth::F32)),
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)),
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)),
) => {
let src_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src);
ASM::to_float_freg32_freg64(&mut self.buf, dst_reg, src_reg);
}
(
Layout::Builtin(Builtin::Float(FloatWidth::F32)),
Layout::Builtin(Builtin::Float(FloatWidth::F64)),
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)),
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)),
) => {
let src_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src);
ASM::to_float_freg64_freg32(&mut self.buf, dst_reg, src_reg);
}
(
Layout::Builtin(Builtin::Float(FloatWidth::F64)),
Layout::Builtin(Builtin::Float(FloatWidth::F64)),
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)),
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)),
) => {
let src_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src);
ASM::mov_freg64_freg64(&mut self.buf, dst_reg, src_reg);
}
(
Layout::Builtin(Builtin::Float(FloatWidth::F32)),
Layout::Builtin(Builtin::Float(FloatWidth::F32)),
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)),
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)),
) => {
let src_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src);
ASM::mov_freg64_freg64(&mut self.buf, dst_reg, src_reg);
@ -1808,8 +1816,10 @@ impl<
let old_element_layout = higher_order.passed_function.argument_layouts[0];
let new_element_layout = higher_order.passed_function.return_layout;
let input_list_layout = Layout::Builtin(Builtin::List(old_element_layout));
let input_list_in_layout = self.layout_interner.insert(input_list_layout);
let input_list_layout = LayoutRepr::Builtin(Builtin::List(old_element_layout));
let input_list_in_layout = self.layout_interner.insert(Layout {
repr: input_list_layout,
});
let caller = self.debug_symbol("caller");
let data = self.debug_symbol("data");
@ -2212,15 +2222,16 @@ impl<
.storage_manager
.claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout));
let ret_fields =
if let Layout::Struct { field_layouts, .. } = self.layout_interner.get(*ret_layout) {
field_layouts
} else {
internal_error!(
"Expected replace to return a struct instead found: {:?}",
ret_layout
)
};
let ret_fields = if let LayoutRepr::Struct { field_layouts, .. } =
self.layout_interner.get(*ret_layout).repr
{
field_layouts
} else {
internal_error!(
"Expected replace to return a struct instead found: {:?}",
ret_layout
)
};
// Only return list and old element.
debug_assert_eq!(ret_fields.len(), 2);
@ -2561,7 +2572,9 @@ impl<
);
}
_ => {
let union_in_layout = self.layout_interner.insert(Layout::Union(*union_layout));
let union_in_layout = self.layout_interner.insert(Layout {
repr: LayoutRepr::Union(*union_layout),
});
todo!(
"loading from union type: {:?}",
self.layout_interner.dbg(union_in_layout)
@ -2673,14 +2686,14 @@ impl<
fn load_literal(&mut self, sym: &Symbol, layout: &InLayout<'a>, lit: &Literal<'a>) {
let layout = self.layout_interner.get(*layout);
if let Layout::LambdaSet(lambda_set) = layout {
if let LayoutRepr::LambdaSet(lambda_set) = layout.repr {
return self.load_literal(sym, &lambda_set.runtime_representation(), lit);
}
match (lit, layout) {
match (lit, layout.repr) {
(
Literal::Int(x),
Layout::Builtin(Builtin::Int(
LayoutRepr::Builtin(Builtin::Int(
IntWidth::U8
| IntWidth::U16
| IntWidth::U32
@ -2697,7 +2710,7 @@ impl<
}
(
Literal::Int(bytes) | Literal::U128(bytes),
Layout::Builtin(Builtin::Int(IntWidth::I128 | IntWidth::U128)),
LayoutRepr::Builtin(Builtin::Int(IntWidth::I128 | IntWidth::U128)),
) => {
self.storage_manager.with_tmp_general_reg(
&mut self.buf,
@ -2717,26 +2730,26 @@ impl<
},
);
}
(Literal::Byte(x), Layout::Builtin(Builtin::Int(IntWidth::U8 | IntWidth::I8))) => {
(Literal::Byte(x), LayoutRepr::Builtin(Builtin::Int(IntWidth::U8 | IntWidth::I8))) => {
let reg = self.storage_manager.claim_general_reg(&mut self.buf, sym);
let val = *x;
ASM::mov_reg64_imm64(&mut self.buf, reg, val as i64);
}
(Literal::Bool(x), Layout::Builtin(Builtin::Bool)) => {
(Literal::Bool(x), LayoutRepr::Builtin(Builtin::Bool)) => {
let reg = self.storage_manager.claim_general_reg(&mut self.buf, sym);
ASM::mov_reg64_imm64(&mut self.buf, reg, *x as i64);
}
(Literal::Float(x), Layout::Builtin(Builtin::Float(FloatWidth::F64))) => {
(Literal::Float(x), LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64))) => {
let reg = self.storage_manager.claim_float_reg(&mut self.buf, sym);
let val = *x;
ASM::mov_freg64_imm64(&mut self.buf, &mut self.relocs, reg, val);
}
(Literal::Float(x), Layout::Builtin(Builtin::Float(FloatWidth::F32))) => {
(Literal::Float(x), LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32))) => {
let reg = self.storage_manager.claim_float_reg(&mut self.buf, sym);
let val = *x as f32;
ASM::mov_freg32_imm32(&mut self.buf, &mut self.relocs, reg, val);
}
(Literal::Decimal(bytes), Layout::Builtin(Builtin::Decimal)) => {
(Literal::Decimal(bytes), LayoutRepr::Builtin(Builtin::Decimal)) => {
self.storage_manager.with_tmp_general_reg(
&mut self.buf,
|storage_manager, buf, reg| {
@ -2755,7 +2768,7 @@ impl<
},
);
}
(Literal::Str(x), Layout::Builtin(Builtin::Str)) => {
(Literal::Str(x), LayoutRepr::Builtin(Builtin::Str)) => {
if x.len() < 24 {
// Load small string.
self.storage_manager.with_tmp_general_reg(
@ -2822,8 +2835,8 @@ impl<
CC::FLOAT_RETURN_REGS[0],
);
}
other => match self.layout_interner.get(other) {
Layout::Boxed(_) => {
other => match self.layout_interner.get(other).repr {
LayoutRepr::Boxed(_) => {
// treat like a 64-bit integer
self.storage_manager.load_to_specified_general_reg(
&mut self.buf,
@ -2831,7 +2844,7 @@ impl<
CC::GENERAL_RETURN_REGS[0],
);
}
Layout::LambdaSet(lambda_set) => {
LayoutRepr::LambdaSet(lambda_set) => {
self.return_symbol(sym, &lambda_set.runtime_representation())
}
_ => {
@ -3327,8 +3340,8 @@ impl<
element_in_layout: InLayout<'a>,
dst: Symbol,
) {
match layout_interner.get(element_in_layout) {
Layout::Builtin(builtin) => match builtin {
match layout_interner.get(element_in_layout).repr {
LayoutRepr::Builtin(builtin) => match builtin {
Builtin::Int(int_width) => match int_width {
IntWidth::I128 | IntWidth::U128 => {
// can we treat this as 2 u64's?
@ -3374,13 +3387,13 @@ impl<
}
},
Layout::Boxed(_) => {
LayoutRepr::Boxed(_) => {
// the same as 64-bit integer (for 64-bit targets)
let dst_reg = storage_manager.claim_general_reg(buf, &dst);
ASM::mov_reg64_mem64_offset32(buf, dst_reg, ptr_reg, 0);
}
Layout::Struct { .. } => {
LayoutRepr::Struct { .. } => {
// put it on the stack
let stack_size = layout_interner.stack_size(element_in_layout);
@ -3389,7 +3402,7 @@ impl<
});
}
Layout::Union(UnionLayout::NonRecursive(_)) => {
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => {
// put it on the stack
let stack_size = layout_interner.stack_size(element_in_layout);
@ -3398,7 +3411,7 @@ impl<
});
}
Layout::LambdaSet(lambda_set) => {
LayoutRepr::LambdaSet(lambda_set) => {
Self::ptr_read(
buf,
storage_manager,
@ -3424,32 +3437,32 @@ impl<
element_layout: Layout<'a>,
value: Symbol,
) {
match element_layout {
Layout::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
match element_layout.repr {
LayoutRepr::Builtin(Builtin::Int(IntWidth::I64 | IntWidth::U64)) => {
let sym_reg = storage_manager.load_to_general_reg(buf, &value);
ASM::mov_mem64_offset32_reg64(buf, ptr_reg, element_offset, sym_reg);
}
Layout::Builtin(Builtin::Int(IntWidth::I32 | IntWidth::U32)) => {
LayoutRepr::Builtin(Builtin::Int(IntWidth::I32 | IntWidth::U32)) => {
let sym_reg = storage_manager.load_to_general_reg(buf, &value);
ASM::mov_mem32_offset32_reg32(buf, ptr_reg, element_offset, sym_reg);
}
Layout::Builtin(Builtin::Int(IntWidth::I16 | IntWidth::U16)) => {
LayoutRepr::Builtin(Builtin::Int(IntWidth::I16 | IntWidth::U16)) => {
let sym_reg = storage_manager.load_to_general_reg(buf, &value);
ASM::mov_mem16_offset32_reg16(buf, ptr_reg, element_offset, sym_reg);
}
Layout::Builtin(Builtin::Int(IntWidth::I8 | IntWidth::U8) | Builtin::Bool) => {
LayoutRepr::Builtin(Builtin::Int(IntWidth::I8 | IntWidth::U8) | Builtin::Bool) => {
let sym_reg = storage_manager.load_to_general_reg(buf, &value);
ASM::mov_mem8_offset32_reg8(buf, ptr_reg, element_offset, sym_reg);
}
Layout::Builtin(Builtin::Float(FloatWidth::F64 | FloatWidth::F32)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64 | FloatWidth::F32)) => {
let sym_reg = storage_manager.load_to_float_reg(buf, &value);
ASM::movesd_mem64_offset32_freg64(buf, ptr_reg, element_offset, sym_reg);
}
Layout::Boxed(_) => {
LayoutRepr::Boxed(_) => {
let sym_reg = storage_manager.load_to_general_reg(buf, &value);
ASM::mov_mem64_offset32_reg64(buf, ptr_reg, element_offset, sym_reg);
}
Layout::LambdaSet(lambda_set) => {
LayoutRepr::LambdaSet(lambda_set) => {
let layout = layout_interner.get(lambda_set.runtime_representation());
Self::ptr_write(

View file

@ -11,7 +11,8 @@ use roc_module::symbol::Symbol;
use roc_mono::{
ir::{JoinPointId, Param},
layout::{
Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, TagIdIntType, UnionLayout,
Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, TagIdIntType,
UnionLayout,
},
};
use roc_target::TargetInfo;
@ -667,13 +668,13 @@ impl<
let mut in_layout = *layout;
let layout = loop {
match layout_interner.get(in_layout) {
Layout::LambdaSet(inner) => in_layout = inner.runtime_representation(),
match layout_interner.get(in_layout).repr {
LayoutRepr::LambdaSet(inner) => in_layout = inner.runtime_representation(),
other => break other,
}
};
if let Layout::Struct { field_layouts, .. } = layout {
if let LayoutRepr::Struct { field_layouts, .. } = layout {
let mut current_offset = base_offset;
for (field, field_layout) in fields.iter().zip(field_layouts.iter()) {
self.copy_symbol_to_stack_offset(
@ -780,8 +781,8 @@ impl<
sym: &Symbol,
layout: &InLayout<'a>,
) {
match layout_interner.get(*layout) {
Layout::Builtin(builtin) => match builtin {
match layout_interner.get(*layout).repr {
LayoutRepr::Builtin(builtin) => match builtin {
Builtin::Int(int_width) => match int_width {
IntWidth::I128 | IntWidth::U128 => {
let (from_offset, size) = self.stack_offset_and_size(sym);
@ -844,13 +845,13 @@ impl<
self.copy_to_stack_offset(buf, size, from_offset, to_offset)
}
},
Layout::Boxed(_) => {
LayoutRepr::Boxed(_) => {
// like a 64-bit integer
debug_assert_eq!(to_offset % 8, 0);
let reg = self.load_to_general_reg(buf, sym);
ASM::mov_base32_reg64(buf, to_offset, reg);
}
Layout::LambdaSet(lambda_set) => {
LayoutRepr::LambdaSet(lambda_set) => {
// like its runtime representation
self.copy_symbol_to_stack_offset(
layout_interner,
@ -861,7 +862,7 @@ impl<
)
}
_ if layout_interner.stack_size(*layout) == 0 => {}
Layout::Struct { .. } | Layout::Union(UnionLayout::NonRecursive(_)) => {
LayoutRepr::Struct { .. } | LayoutRepr::Union(UnionLayout::NonRecursive(_)) => {
let (from_offset, size) = self.stack_offset_and_size(sym);
debug_assert_eq!(size, layout_interner.stack_size(*layout));
@ -1172,7 +1173,7 @@ impl<
.insert(symbol, Rc::new((base_offset, 8)));
}
_ => {
if let Layout::LambdaSet(lambda_set) = layout_interner.get(layout) {
if let LayoutRepr::LambdaSet(lambda_set) = layout_interner.get(layout).repr {
self.joinpoint_argument_stack_storage(
layout_interner,
symbol,
@ -1236,7 +1237,7 @@ impl<
ASM::mov_base32_freg64(buf, base_offset, reg);
}
_ => {
if let Layout::LambdaSet(lambda_set) = layout_interner.get(layout) {
if let LayoutRepr::LambdaSet(lambda_set) = layout_interner.get(layout).repr {
self.jump_argument_stack_storage(
layout_interner,
buf,
@ -1535,9 +1536,9 @@ impl<
fn is_primitive(layout_interner: &mut STLayoutInterner<'_>, layout: InLayout<'_>) -> bool {
match layout {
single_register_layouts!() => true,
_ => match layout_interner.get(layout) {
Layout::Boxed(_) => true,
Layout::LambdaSet(lambda_set) => {
_ => match layout_interner.get(layout).repr {
LayoutRepr::Boxed(_) => true,
LayoutRepr::LambdaSet(lambda_set) => {
is_primitive(layout_interner, lambda_set.runtime_representation())
}
_ => false,

View file

@ -7,7 +7,9 @@ use bumpalo::collections::Vec;
use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_error_macros::internal_error;
use roc_module::symbol::Symbol;
use roc_mono::layout::{Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, UnionLayout};
use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout,
};
use super::{CompareOperation, RegisterWidth};
@ -507,19 +509,19 @@ impl X64_64SystemVStoreArgs {
}
other => {
// look at the layout in more detail
match layout_interner.get(other) {
Layout::Boxed(_) => {
match layout_interner.get(other).repr {
LayoutRepr::Boxed(_) => {
// treat boxed like a 64-bit integer
self.store_arg_general(buf, storage_manager, sym)
}
Layout::LambdaSet(lambda_set) => self.store_arg(
LayoutRepr::LambdaSet(lambda_set) => self.store_arg(
buf,
storage_manager,
layout_interner,
sym,
lambda_set.runtime_representation(),
),
Layout::Struct { .. } => {
LayoutRepr::Struct { .. } => {
// for now, just also store this on the stack
let (base_offset, size) = storage_manager.stack_offset_and_size(&sym);
debug_assert_eq!(base_offset % 8, 0);
@ -537,7 +539,7 @@ impl X64_64SystemVStoreArgs {
}
self.tmp_stack_offset += size as i32;
}
Layout::Union(UnionLayout::NonRecursive(_)) => {
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => {
type ASM = X86_64Assembler;
let tmp_reg = Self::GENERAL_RETURN_REGS[0];
@ -668,27 +670,27 @@ impl X64_64SystemVLoadArgs {
storage_manager.complex_stack_arg(&sym, self.argument_offset, stack_size);
self.argument_offset += stack_size as i32;
}
other => match layout_interner.get(other) {
Layout::Boxed(_) => {
other => match layout_interner.get(other).repr {
LayoutRepr::Boxed(_) => {
// boxed layouts are pointers, which we treat as 64-bit integers
self.load_arg_general(storage_manager, sym)
}
Layout::LambdaSet(lambda_set) => self.load_arg(
LayoutRepr::LambdaSet(lambda_set) => self.load_arg(
storage_manager,
layout_interner,
sym,
lambda_set.runtime_representation(),
),
Layout::Struct { .. } => {
LayoutRepr::Struct { .. } => {
// for now, just also store this on the stack
storage_manager.complex_stack_arg(&sym, self.argument_offset, stack_size);
self.argument_offset += stack_size as i32;
}
Layout::Builtin(Builtin::Int(IntWidth::U128 | IntWidth::I128)) => {
LayoutRepr::Builtin(Builtin::Int(IntWidth::U128 | IntWidth::I128)) => {
storage_manager.complex_stack_arg(&sym, self.argument_offset, stack_size);
self.argument_offset += stack_size as i32;
}
Layout::Union(UnionLayout::NonRecursive(_)) => {
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => {
// for now, just also store this on the stack
storage_manager.complex_stack_arg(&sym, self.argument_offset, stack_size);
self.argument_offset += stack_size as i32;

View file

@ -18,8 +18,8 @@ use roc_mono::ir::{
Literal, Param, Proc, ProcLayout, SelfRecursive, Stmt,
};
use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, TagIdIntType,
UnionLayout,
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, LayoutRepr, STLayoutInterner,
TagIdIntType, UnionLayout,
};
use roc_mono::list_element_layout;
@ -174,8 +174,8 @@ trait Backend<'a> {
}
fn list_argument(&mut self, list_layout: InLayout<'a>) -> ListArgument<'a> {
let element_layout = match self.interner().get(list_layout) {
Layout::Builtin(Builtin::List(e)) => e,
let element_layout = match self.interner().get(list_layout).repr {
LayoutRepr::Builtin(Builtin::List(e)) => e,
_ => unreachable!(),
};
@ -196,7 +196,9 @@ trait Backend<'a> {
}
fn increment_fn_pointer(&mut self, layout: InLayout<'a>) -> Symbol {
let box_layout = self.interner_mut().insert(Layout::Boxed(layout));
let box_layout = self.interner_mut().insert(Layout {
repr: LayoutRepr::Boxed(layout),
});
let element_increment = self.debug_symbol("element_increment");
let element_increment_symbol = self.build_indirect_inc(layout);
@ -214,7 +216,9 @@ trait Backend<'a> {
}
fn decrement_fn_pointer(&mut self, layout: InLayout<'a>) -> Symbol {
let box_layout = self.interner_mut().insert(Layout::Boxed(layout));
let box_layout = self.interner_mut().insert(Layout {
repr: LayoutRepr::Boxed(layout),
});
let element_decrement = self.debug_symbol("element_decrement");
let element_decrement_symbol = self.build_indirect_dec(layout);
@ -609,8 +613,8 @@ trait Backend<'a> {
self.tag(sym, arguments, tag_layout, *tag_id);
}
Expr::ExprBox { symbol: value } => {
let element_layout = match self.interner().get(*layout) {
Layout::Boxed(boxed) => boxed,
let element_layout = match self.interner().get(*layout).repr {
LayoutRepr::Boxed(boxed) => boxed,
_ => unreachable!("{:?}", self.interner().dbg(*layout)),
};
@ -782,78 +786,90 @@ trait Backend<'a> {
);
self.build_num_sub_wrap(sym, &args[0], &args[1], ret_layout)
}
LowLevel::NumSubSaturated => match self.interner().get(*ret_layout) {
Layout::Builtin(Builtin::Int(int_width)) => self.build_fn_call(
LowLevel::NumSubSaturated => match self.interner().get(*ret_layout).repr {
LayoutRepr::Builtin(Builtin::Int(int_width)) => self.build_fn_call(
sym,
bitcode::NUM_SUB_SATURATED_INT[int_width].to_string(),
args,
arg_layouts,
ret_layout,
),
Layout::Builtin(Builtin::Float(FloatWidth::F32)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
self.build_num_sub(sym, &args[0], &args[1], ret_layout)
}
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
// saturated sub is just normal sub
self.build_num_sub(sym, &args[0], &args[1], ret_layout)
}
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
// self.load_args_and_call_zig(backend, bitcode::DEC_SUB_SATURATED)
todo!()
}
_ => internal_error!("invalid return type"),
},
LowLevel::NumBitwiseAnd => {
if let Layout::Builtin(Builtin::Int(int_width)) = self.interner().get(*ret_layout) {
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
self.interner().get(*ret_layout).repr
{
self.build_int_bitwise_and(sym, &args[0], &args[1], int_width)
} else {
internal_error!("bitwise and on a non-integer")
}
}
LowLevel::NumBitwiseOr => {
if let Layout::Builtin(Builtin::Int(int_width)) = self.interner().get(*ret_layout) {
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
self.interner().get(*ret_layout).repr
{
self.build_int_bitwise_or(sym, &args[0], &args[1], int_width)
} else {
internal_error!("bitwise or on a non-integer")
}
}
LowLevel::NumBitwiseXor => {
if let Layout::Builtin(Builtin::Int(int_width)) = self.interner().get(*ret_layout) {
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
self.interner().get(*ret_layout).repr
{
self.build_int_bitwise_xor(sym, &args[0], &args[1], int_width)
} else {
internal_error!("bitwise xor on a non-integer")
}
}
LowLevel::And => {
if let Layout::Builtin(Builtin::Bool) = self.interner().get(*ret_layout) {
if let LayoutRepr::Builtin(Builtin::Bool) = self.interner().get(*ret_layout).repr {
self.build_int_bitwise_and(sym, &args[0], &args[1], IntWidth::U8)
} else {
internal_error!("bitwise and on a non-integer")
}
}
LowLevel::Or => {
if let Layout::Builtin(Builtin::Bool) = self.interner().get(*ret_layout) {
if let LayoutRepr::Builtin(Builtin::Bool) = self.interner().get(*ret_layout).repr {
self.build_int_bitwise_or(sym, &args[0], &args[1], IntWidth::U8)
} else {
internal_error!("bitwise or on a non-integer")
}
}
LowLevel::NumShiftLeftBy => {
if let Layout::Builtin(Builtin::Int(int_width)) = self.interner().get(*ret_layout) {
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
self.interner().get(*ret_layout).repr
{
self.build_int_shift_left(sym, &args[0], &args[1], int_width)
} else {
internal_error!("shift left on a non-integer")
}
}
LowLevel::NumShiftRightBy => {
if let Layout::Builtin(Builtin::Int(int_width)) = self.interner().get(*ret_layout) {
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
self.interner().get(*ret_layout).repr
{
self.build_int_shift_right(sym, &args[0], &args[1], int_width)
} else {
internal_error!("shift right on a non-integer")
}
}
LowLevel::NumShiftRightZfBy => {
if let Layout::Builtin(Builtin::Int(int_width)) = self.interner().get(*ret_layout) {
if let LayoutRepr::Builtin(Builtin::Int(int_width)) =
self.interner().get(*ret_layout).repr
{
self.build_int_shift_right_zero_fill(sym, &args[0], &args[1], int_width)
} else {
internal_error!("shift right zero-fill on a non-integer")
@ -1273,18 +1289,18 @@ trait Backend<'a> {
ret_layout,
),
LowLevel::StrToNum => {
let number_layout = match self.interner().get(*ret_layout) {
Layout::Struct { field_layouts, .. } => field_layouts[0], // TODO: why is it sometimes a struct?
let number_layout = match self.interner().get(*ret_layout).repr {
LayoutRepr::Struct { field_layouts, .. } => field_layouts[0], // TODO: why is it sometimes a struct?
_ => unreachable!(),
};
// match on the return layout to figure out which zig builtin we need
let intrinsic = match self.interner().get(number_layout) {
Layout::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
Layout::Builtin(Builtin::Float(float_width)) => {
let intrinsic = match self.interner().get(number_layout).repr {
LayoutRepr::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
&bitcode::STR_TO_FLOAT[float_width]
}
Layout::Builtin(Builtin::Decimal) => bitcode::DEC_FROM_STR,
LayoutRepr::Builtin(Builtin::Decimal) => bitcode::DEC_FROM_STR,
_ => unreachable!(),
};
@ -1299,8 +1315,8 @@ trait Backend<'a> {
self.build_ptr_cast(sym, &args[0])
}
LowLevel::PtrWrite => {
let element_layout = match self.interner().get(*ret_layout) {
Layout::Boxed(boxed) => boxed,
let element_layout = match self.interner().get(*ret_layout).repr {
LayoutRepr::Boxed(boxed) => boxed,
_ => unreachable!("cannot write to {:?}", self.interner().dbg(*ret_layout)),
};
@ -1343,10 +1359,10 @@ trait Backend<'a> {
),
LowLevel::NumToStr => {
let arg_layout = arg_layouts[0];
let intrinsic = match self.interner().get(arg_layout) {
Layout::Builtin(Builtin::Int(width)) => &bitcode::STR_FROM_INT[width],
Layout::Builtin(Builtin::Float(width)) => &bitcode::STR_FROM_FLOAT[width],
Layout::Builtin(Builtin::Decimal) => bitcode::DEC_TO_STR,
let intrinsic = match self.interner().get(arg_layout).repr {
LayoutRepr::Builtin(Builtin::Int(width)) => &bitcode::STR_FROM_INT[width],
LayoutRepr::Builtin(Builtin::Float(width)) => &bitcode::STR_FROM_FLOAT[width],
LayoutRepr::Builtin(Builtin::Decimal) => bitcode::DEC_TO_STR,
x => internal_error!("NumToStr is not defined for {:?}", x),
};
@ -1357,13 +1373,13 @@ trait Backend<'a> {
self.build_fn_call(sym, intrinsic, args, arg_layouts, ret_layout);
}
LowLevel::NumIntCast => {
let source_width = match self.interner().get(arg_layouts[0]) {
Layout::Builtin(Builtin::Int(width)) => width,
let source_width = match self.interner().get(arg_layouts[0]).repr {
LayoutRepr::Builtin(Builtin::Int(width)) => width,
_ => unreachable!(),
};
let target_width = match self.interner().get(*ret_layout) {
Layout::Builtin(Builtin::Int(width)) => width,
let target_width = match self.interner().get(*ret_layout).repr {
LayoutRepr::Builtin(Builtin::Int(width)) => width,
_ => unreachable!(),
};

View file

@ -456,9 +456,9 @@ fn build_exposed_generic_proc<'a, B: Backend<'a>>(backend: &mut B, proc: &Proc<'
let s2 = backend.debug_symbol_in(platform, "s2");
let s3 = backend.debug_symbol_in(platform, "s3");
let box_layout = backend
.interner_mut()
.insert(roc_mono::layout::Layout::Boxed(proc.ret_layout));
let box_layout = backend.interner_mut().insert(Layout {
repr: roc_mono::layout::LayoutRepr::Boxed(proc.ret_layout),
});
let mut args = bumpalo::collections::Vec::new_in(arena);
args.extend(proc.args);

View file

@ -18,7 +18,7 @@ use inkwell::AddressSpace;
use roc_error_macros::internal_error;
use roc_module::symbol::Symbol;
use roc_mono::layout::{
Builtin, InLayout, LambdaSet, Layout, LayoutIds, LayoutInterner, STLayoutInterner,
Builtin, InLayout, LambdaSet, LayoutIds, LayoutInterner, LayoutRepr, STLayoutInterner,
};
use super::build::{create_entry_block_alloca, BuilderExt};
@ -610,8 +610,8 @@ pub fn build_compare_wrapper<'a, 'ctx>(
let closure_data_repr = closure_data_layout.runtime_representation();
let arguments_cast = match layout_interner.get(closure_data_repr) {
Layout::Struct {
let arguments_cast = match layout_interner.get(closure_data_repr).repr {
LayoutRepr::Struct {
field_layouts: &[], ..
} => {
// nothing to add

View file

@ -43,7 +43,7 @@ use roc_mono::ir::{
ListLiteralElement, ModifyRc, OptLevel, ProcLayout, SingleEntryPoint,
};
use roc_mono::layout::{
Builtin, InLayout, LambdaName, LambdaSet, Layout, LayoutIds, LayoutInterner, Niche,
Builtin, InLayout, LambdaName, LambdaSet, Layout, LayoutIds, LayoutInterner, LayoutRepr, Niche,
RawFunctionLayout, STLayoutInterner, TagIdIntType, UnionLayout,
};
use roc_std::RocDec;
@ -783,13 +783,13 @@ pub fn build_exp_literal<'a, 'ctx>(
use roc_mono::ir::Literal::*;
match literal {
Int(bytes) => match layout_interner.get(layout) {
Layout::Builtin(Builtin::Bool) => env
Int(bytes) => match layout_interner.get(layout).repr {
LayoutRepr::Builtin(Builtin::Bool) => env
.context
.bool_type()
.const_int(i128::from_ne_bytes(*bytes) as u64, false)
.into(),
Layout::Builtin(Builtin::Int(int_width)) => {
LayoutRepr::Builtin(Builtin::Int(int_width)) => {
int_with_precision(env, i128::from_ne_bytes(*bytes), int_width).into()
}
_ => panic!("Invalid layout for int literal = {:?}", layout),
@ -797,8 +797,8 @@ pub fn build_exp_literal<'a, 'ctx>(
U128(bytes) => const_u128(env, u128::from_ne_bytes(*bytes)).into(),
Float(float) => match layout_interner.get(layout) {
Layout::Builtin(Builtin::Float(float_width)) => {
Float(float) => match layout_interner.get(layout).repr {
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
float_with_precision(env, *float, float_width)
}
_ => panic!("Invalid layout for float literal = {:?}", layout),
@ -1178,8 +1178,8 @@ pub fn build_exp_expr<'a, 'ctx>(
let tag_ptr = tag_ptr.into_pointer_value();
// reset is only generated for union values
let union_layout = match layout_interner.get(layout) {
Layout::Union(ul) => ul,
let union_layout = match layout_interner.get(layout).repr {
LayoutRepr::Union(ul) => ul,
_ => unreachable!(),
};
@ -1285,15 +1285,16 @@ pub fn build_exp_expr<'a, 'ctx>(
} => {
let (value, layout) = load_symbol_and_layout(scope, structure);
let layout = if let Layout::LambdaSet(lambda_set) = layout_interner.get(layout) {
let layout = if let LayoutRepr::LambdaSet(lambda_set) = layout_interner.get(layout).repr
{
lambda_set.runtime_representation()
} else {
layout
};
// extract field from a record
match (value, layout_interner.get(layout)) {
(StructValue(argument), Layout::Struct { field_layouts, .. }) => {
match (value, layout_interner.get(layout).repr) {
(StructValue(argument), LayoutRepr::Struct { field_layouts, .. }) => {
debug_assert!(!field_layouts.is_empty());
let field_value = env
@ -1586,7 +1587,7 @@ fn build_tag_field_value<'a, 'ctx>(
value: BasicValueEnum<'ctx>,
tag_field_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
if let Layout::RecursivePointer(_) = layout_interner.get(tag_field_layout) {
if let LayoutRepr::RecursivePointer(_) = layout_interner.get(tag_field_layout).repr {
debug_assert!(value.is_pointer_value());
// we store recursive pointers as `i64*`
@ -1741,7 +1742,9 @@ fn build_tag<'a, 'ctx>(
use std::cmp::Ordering::*;
match tag_id.cmp(&(*nullable_id as _)) {
Equal => {
let layout = layout_interner.insert(Layout::Union(*union_layout));
let layout = layout_interner.insert(Layout {
repr: LayoutRepr::Union(*union_layout),
});
return basic_type_from_layout(env, layout_interner, layout)
.into_pointer_type()
@ -2505,8 +2508,8 @@ pub fn build_exp_stmt<'a, 'ctx>(
for (symbol, expr, layout) in queue {
debug_assert!(!matches!(
layout_interner.get(*layout),
Layout::RecursivePointer(_)
layout_interner.get(*layout).repr,
LayoutRepr::RecursivePointer(_)
));
let val = build_exp_expr(
@ -2805,9 +2808,10 @@ pub fn build_exp_stmt<'a, 'ctx>(
DecRef(symbol) => {
let (value, layout) = load_symbol_and_layout(scope, symbol);
match layout_interner.get(layout) {
Layout::Builtin(Builtin::Str) => todo!(),
Layout::Builtin(Builtin::List(element_layout)) => {
let lay = layout_interner.get(layout);
match lay.repr {
LayoutRepr::Builtin(Builtin::Str) => todo!(),
LayoutRepr::Builtin(Builtin::List(element_layout)) => {
debug_assert!(value.is_struct_value());
let element_layout = layout_interner.get(element_layout);
let alignment =
@ -2816,7 +2820,7 @@ pub fn build_exp_stmt<'a, 'ctx>(
build_list::decref(env, value.into_struct_value(), alignment);
}
lay if lay.is_refcounted() => {
_ if lay.is_refcounted() => {
if value.is_pointer_value() {
let value_ptr = value.into_pointer_value();
@ -3388,8 +3392,8 @@ fn build_switch_ir<'a, 'ctx>(
let cont_block = context.append_basic_block(parent, "cont");
// Build the condition
let cond = match layout_interner.get(cond_layout) {
Layout::Builtin(Builtin::Float(float_width)) => {
let cond = match layout_interner.get(cond_layout).repr {
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
// float matches are done on the bit pattern
cond_layout = Layout::float_width(float_width);
@ -3402,19 +3406,19 @@ fn build_switch_ir<'a, 'ctx>(
.build_bitcast(cond_value, int_type, "")
.into_int_value()
}
Layout::Union(variant) => {
LayoutRepr::Union(variant) => {
cond_layout = variant.tag_id_layout();
get_tag_id(env, layout_interner, parent, &variant, cond_value)
}
Layout::Builtin(_) => cond_value.into_int_value(),
LayoutRepr::Builtin(_) => cond_value.into_int_value(),
other => todo!("Build switch value from layout: {:?}", other),
};
// Build the cases
let mut incoming = Vec::with_capacity_in(branches.len(), arena);
if let Layout::Builtin(Builtin::Bool) = layout_interner.get(cond_layout) {
if let LayoutRepr::Builtin(Builtin::Bool) = layout_interner.get(cond_layout).repr {
match (branches, default_branch) {
([(0, _, false_branch)], true_branch) | ([(1, _, true_branch)], false_branch) => {
let then_block = context.append_basic_block(parent, "then_block");
@ -3822,8 +3826,8 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>(
// the C and Fast calling conventions agree
arguments_for_call.push(*arg);
} else {
match layout_interner.get(*layout) {
Layout::Builtin(Builtin::List(_)) => {
match layout_interner.get(*layout).repr {
LayoutRepr::Builtin(Builtin::List(_)) => {
let list_type = arg_type
.into_pointer_type()
.get_element_type()
@ -3961,7 +3965,7 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>(
};
for (i, layout) in arguments.iter().enumerate() {
if let Layout::Builtin(Builtin::Str) = layout_interner.get(*layout) {
if let LayoutRepr::Builtin(Builtin::Str) = layout_interner.get(*layout).repr {
// Indicate to LLVM that this argument is semantically passed by-value
// even though technically (because of its size) it is passed by-reference
let byval_attribute_id = Attribute::get_named_enum_kind_id("byval");
@ -4061,8 +4065,10 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>(
env.target_info.architecture,
roc_target::Architecture::X86_32 | roc_target::Architecture::X86_64
) {
let c_abi_type = match layout_interner.get(*layout) {
Layout::Builtin(Builtin::Str | Builtin::List(_)) => c_abi_roc_str_type,
let c_abi_type = match layout_interner.get(*layout).repr {
LayoutRepr::Builtin(Builtin::Str | Builtin::List(_)) => {
c_abi_roc_str_type
}
_ => todo!("figure out what the C type is"),
};
@ -5628,8 +5634,8 @@ fn to_cc_type<'a, 'ctx>(
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
) -> BasicTypeEnum<'ctx> {
match layout_interner.runtime_representation(layout) {
Layout::Builtin(builtin) => to_cc_type_builtin(env, &builtin),
match layout_interner.runtime_representation(layout).repr {
LayoutRepr::Builtin(builtin) => to_cc_type_builtin(env, &builtin),
_ => {
// TODO this is almost certainly incorrect for bigger structs
basic_type_from_layout(env, layout_interner, layout)
@ -5675,8 +5681,8 @@ impl RocReturn {
target_info: TargetInfo,
layout: InLayout,
) -> bool {
match interner.get(layout) {
Layout::Builtin(builtin) => {
match interner.get(layout).repr {
LayoutRepr::Builtin(builtin) => {
use Builtin::*;
match target_info.ptr_width() {
@ -5688,8 +5694,8 @@ impl RocReturn {
}
}
}
Layout::Union(UnionLayout::NonRecursive(_)) => true,
Layout::LambdaSet(lambda_set) => RocReturn::roc_return_by_pointer(
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => true,
LayoutRepr::LambdaSet(lambda_set) => RocReturn::roc_return_by_pointer(
interner,
target_info,
lambda_set.runtime_representation(),

View file

@ -11,7 +11,7 @@ use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_error_macros::internal_error;
use roc_module::symbol::Symbol;
use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, UnionLayout,
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout,
};
use super::build::{load_roc_value, use_roc_value, BuilderExt};
@ -154,8 +154,8 @@ fn build_eq<'a, 'ctx>(
);
}
match layout_interner.get(*lhs_layout) {
Layout::Builtin(builtin) => build_eq_builtin(
match layout_interner.get(*lhs_layout).repr {
LayoutRepr::Builtin(builtin) => build_eq_builtin(
env,
layout_interner,
layout_ids,
@ -165,7 +165,7 @@ fn build_eq<'a, 'ctx>(
&builtin,
),
Layout::Struct { field_layouts, .. } => build_struct_eq(
LayoutRepr::Struct { field_layouts, .. } => build_struct_eq(
env,
layout_interner,
layout_ids,
@ -175,9 +175,9 @@ fn build_eq<'a, 'ctx>(
rhs_val.into_struct_value(),
),
Layout::LambdaSet(_) => unreachable!("cannot compare closures"),
LayoutRepr::LambdaSet(_) => unreachable!("cannot compare closures"),
Layout::Union(union_layout) => build_tag_eq(
LayoutRepr::Union(union_layout) => build_tag_eq(
env,
layout_interner,
layout_ids,
@ -187,7 +187,7 @@ fn build_eq<'a, 'ctx>(
rhs_val,
),
Layout::Boxed(inner_layout) => build_box_eq(
LayoutRepr::Boxed(inner_layout) => build_box_eq(
env,
layout_interner,
layout_ids,
@ -197,7 +197,7 @@ fn build_eq<'a, 'ctx>(
rhs_val,
),
Layout::RecursivePointer(rec_layout) => {
LayoutRepr::RecursivePointer(rec_layout) => {
let layout = rec_layout;
let bt = basic_type_from_layout(env, layout_interner, layout);
@ -215,8 +215,8 @@ fn build_eq<'a, 'ctx>(
"i64_to_opaque",
);
let union_layout = match layout_interner.get(rec_layout) {
Layout::Union(union_layout) => {
let union_layout = match layout_interner.get(rec_layout).repr {
LayoutRepr::Union(union_layout) => {
debug_assert!(!matches!(union_layout, UnionLayout::NonRecursive(..)));
union_layout
}
@ -342,8 +342,8 @@ fn build_neq<'a, 'ctx>(
);
}
match layout_interner.get(lhs_layout) {
Layout::Builtin(builtin) => build_neq_builtin(
match layout_interner.get(lhs_layout).repr {
LayoutRepr::Builtin(builtin) => build_neq_builtin(
env,
layout_interner,
layout_ids,
@ -353,7 +353,7 @@ fn build_neq<'a, 'ctx>(
&builtin,
),
Layout::Struct { field_layouts, .. } => {
LayoutRepr::Struct { field_layouts, .. } => {
let is_equal = build_struct_eq(
env,
layout_interner,
@ -370,7 +370,7 @@ fn build_neq<'a, 'ctx>(
result.into()
}
Layout::Union(union_layout) => {
LayoutRepr::Union(union_layout) => {
let is_equal = build_tag_eq(
env,
layout_interner,
@ -387,7 +387,7 @@ fn build_neq<'a, 'ctx>(
result.into()
}
Layout::Boxed(inner_layout) => {
LayoutRepr::Boxed(inner_layout) => {
let is_equal = build_box_eq(
env,
layout_interner,
@ -404,10 +404,10 @@ fn build_neq<'a, 'ctx>(
result.into()
}
Layout::RecursivePointer(_) => {
LayoutRepr::RecursivePointer(_) => {
unreachable!("recursion pointers should never be compared directly")
}
Layout::LambdaSet(_) => unreachable!("cannot compare closure"),
LayoutRepr::LambdaSet(_) => unreachable!("cannot compare closure"),
}
}
@ -424,12 +424,12 @@ fn build_list_eq<'a, 'ctx>(
let di_location = env.builder.get_current_debug_location().unwrap();
let symbol = Symbol::LIST_EQ;
let element_layout = if let Layout::RecursivePointer(rec) = layout_interner.get(element_layout)
{
rec
} else {
element_layout
};
let element_layout =
if let LayoutRepr::RecursivePointer(rec) = layout_interner.get(element_layout).repr {
rec
} else {
element_layout
};
let fn_name = layout_ids
.get(symbol, &element_layout)
.to_symbol_string(symbol, &env.interns);
@ -741,11 +741,11 @@ fn build_struct_eq_help<'a, 'ctx>(
.build_extract_value(struct2, index as u32, "eq_field")
.unwrap();
let are_equal = if let Layout::RecursivePointer(rec_layout) =
layout_interner.get(*field_layout)
let are_equal = if let LayoutRepr::RecursivePointer(rec_layout) =
layout_interner.get(*field_layout).repr
{
debug_assert!(
matches!(layout_interner.get(rec_layout), Layout::Union(union_layout) if !matches!(union_layout, UnionLayout::NonRecursive(..)))
matches!(layout_interner.get(rec_layout).repr, LayoutRepr::Union(union_layout) if !matches!(union_layout, UnionLayout::NonRecursive(..)))
);
let field_layout = rec_layout;

View file

@ -6,7 +6,8 @@ use inkwell::values::StructValue;
use inkwell::AddressSpace;
use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_mono::layout::{
round_up_to_alignment, Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, UnionLayout,
round_up_to_alignment, Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner,
UnionLayout,
};
use roc_target::TargetInfo;
@ -33,9 +34,9 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
layout_interner: &'env mut STLayoutInterner<'a>,
layout: InLayout<'_>,
) -> BasicTypeEnum<'ctx> {
use Layout::*;
use LayoutRepr::*;
match layout_interner.get(layout) {
match layout_interner.get(layout).repr {
Struct {
field_layouts: sorted_fields,
..
@ -150,9 +151,9 @@ pub fn argument_type_from_layout<'a, 'ctx>(
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
) -> BasicTypeEnum<'ctx> {
use Layout::*;
use LayoutRepr::*;
match layout_interner.get(layout) {
match layout_interner.get(layout).repr {
LambdaSet(lambda_set) => {
argument_type_from_layout(env, layout_interner, lambda_set.runtime_representation())
}

View file

@ -13,7 +13,7 @@ use roc_error_macros::internal_error;
use roc_module::symbol::Symbol;
use roc_mono::ir::LookupType;
use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, UnionLayout,
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout,
};
use roc_region::all::Region;
@ -296,8 +296,8 @@ fn build_clone<'a, 'ctx>(
value: BasicValueEnum<'ctx>,
layout: InLayout<'a>,
) -> IntValue<'ctx> {
match layout_interner.get(layout) {
Layout::Builtin(builtin) => build_clone_builtin(
match layout_interner.get(layout).repr {
LayoutRepr::Builtin(builtin) => build_clone_builtin(
env,
layout_interner,
layout_ids,
@ -307,7 +307,7 @@ fn build_clone<'a, 'ctx>(
builtin,
),
Layout::Struct { field_layouts, .. } => build_clone_struct(
LayoutRepr::Struct { field_layouts, .. } => build_clone_struct(
env,
layout_interner,
layout_ids,
@ -319,9 +319,9 @@ fn build_clone<'a, 'ctx>(
// Since we will never actually display functions (and hence lambda sets)
// we just write nothing to the buffer
Layout::LambdaSet(_) => cursors.extra_offset,
LayoutRepr::LambdaSet(_) => cursors.extra_offset,
Layout::Union(union_layout) => {
LayoutRepr::Union(union_layout) => {
if layout_interner.safe_to_memcpy(layout) {
let ptr = unsafe {
env.builder.new_build_in_bounds_gep(
@ -353,7 +353,7 @@ fn build_clone<'a, 'ctx>(
}
}
Layout::Boxed(inner_layout) => {
LayoutRepr::Boxed(inner_layout) => {
// write the offset
build_copy(env, ptr, cursors.offset, cursors.extra_offset.into());
@ -384,7 +384,7 @@ fn build_clone<'a, 'ctx>(
)
}
Layout::RecursivePointer(rec_layout) => {
LayoutRepr::RecursivePointer(rec_layout) => {
let layout = rec_layout;
let bt = basic_type_from_layout(env, layout_interner, layout);
@ -396,8 +396,8 @@ fn build_clone<'a, 'ctx>(
"i64_to_opaque",
);
let union_layout = match layout_interner.get(rec_layout) {
Layout::Union(union_layout) => {
let union_layout = match layout_interner.get(rec_layout).repr {
LayoutRepr::Union(union_layout) => {
debug_assert!(!matches!(union_layout, UnionLayout::NonRecursive(..)));
union_layout
}
@ -476,7 +476,9 @@ fn build_clone_tag<'a, 'ctx>(
value: BasicValueEnum<'ctx>,
union_layout: UnionLayout<'a>,
) -> IntValue<'ctx> {
let layout = layout_interner.insert(Layout::Union(union_layout));
let layout = layout_interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
});
let layout_id = layout_ids.get(Symbol::CLONE, &layout);
let fn_name = layout_id.to_symbol_string(Symbol::CLONE, &env.interns);

View file

@ -12,7 +12,10 @@ use roc_error_macros::internal_error;
use roc_module::{low_level::LowLevel, symbol::Symbol};
use roc_mono::{
ir::HigherOrderLowLevel,
layout::{Builtin, InLayout, LambdaSet, Layout, LayoutIds, LayoutInterner, STLayoutInterner},
layout::{
Builtin, InLayout, LambdaSet, Layout, LayoutIds, LayoutInterner, LayoutRepr,
STLayoutInterner,
},
list_element_layout,
};
use roc_target::PtrWidth;
@ -193,16 +196,18 @@ pub(crate) fn run_low_level<'a, 'ctx>(
// Str.toNum : Str -> Result (Num *) {}
arguments!(string);
let number_layout = match layout_interner.get(layout) {
Layout::Struct { field_layouts, .. } => field_layouts[0], // TODO: why is it sometimes a struct?
let number_layout = match layout_interner.get(layout).repr {
LayoutRepr::Struct { field_layouts, .. } => field_layouts[0], // TODO: why is it sometimes a struct?
_ => unreachable!(),
};
// match on the return layout to figure out which zig builtin we need
let intrinsic = match layout_interner.get(number_layout) {
Layout::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
Layout::Builtin(Builtin::Float(float_width)) => &bitcode::STR_TO_FLOAT[float_width],
Layout::Builtin(Builtin::Decimal) => bitcode::DEC_FROM_STR,
let intrinsic = match layout_interner.get(number_layout).repr {
LayoutRepr::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
&bitcode::STR_TO_FLOAT[float_width]
}
LayoutRepr::Builtin(Builtin::Decimal) => bitcode::DEC_FROM_STR,
_ => unreachable!(),
};
@ -220,9 +225,11 @@ pub(crate) fn run_low_level<'a, 'ctx>(
intrinsic,
),
None => {
let return_type_name = match layout_interner.get(number_layout) {
Layout::Builtin(Builtin::Int(int_width)) => int_width.type_name(),
Layout::Builtin(Builtin::Decimal) => {
let return_type_name = match layout_interner.get(number_layout).repr {
LayoutRepr::Builtin(Builtin::Int(int_width)) => {
int_width.type_name()
}
LayoutRepr::Builtin(Builtin::Decimal) => {
// zig picks 128 for dec.RocDec
"i128"
}
@ -268,12 +275,12 @@ pub(crate) fn run_low_level<'a, 'ctx>(
}
}
PtrWidth::Bytes8 => {
let cc_return_by_pointer = match layout_interner.get(number_layout) {
Layout::Builtin(Builtin::Int(int_width)) => {
let cc_return_by_pointer = match layout_interner.get(number_layout).repr {
LayoutRepr::Builtin(Builtin::Int(int_width)) => {
(int_width.stack_size() as usize > env.target_info.ptr_size())
.then_some(int_width.type_name())
}
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
// zig picks 128 for dec.RocDec
Some("i128")
}
@ -314,8 +321,8 @@ pub(crate) fn run_low_level<'a, 'ctx>(
let (int, int_layout) = load_symbol_and_layout(scope, &args[0]);
let int = int.into_int_value();
let int_width = match layout_interner.get(int_layout) {
Layout::Builtin(Builtin::Int(int_width)) => int_width,
let int_width = match layout_interner.get(int_layout).repr {
LayoutRepr::Builtin(Builtin::Int(int_width)) => int_width,
_ => unreachable!(),
};
@ -333,8 +340,8 @@ pub(crate) fn run_low_level<'a, 'ctx>(
let (float, float_layout) = load_symbol_and_layout(scope, &args[0]);
let float_width = match layout_interner.get(float_layout) {
Layout::Builtin(Builtin::Float(float_width)) => float_width,
let float_width = match layout_interner.get(float_layout).repr {
LayoutRepr::Builtin(Builtin::Float(float_width)) => float_width,
_ => unreachable!(),
};
@ -843,8 +850,8 @@ pub(crate) fn run_low_level<'a, 'ctx>(
// Num.toStr : Num a -> Str
arguments_with_layouts!((num, num_layout));
match layout_interner.get(num_layout) {
Layout::Builtin(Builtin::Int(int_width)) => {
match layout_interner.get(num_layout).repr {
LayoutRepr::Builtin(Builtin::Int(int_width)) => {
let int = num.into_int_value();
call_str_bitcode_fn(
@ -855,11 +862,11 @@ pub(crate) fn run_low_level<'a, 'ctx>(
&bitcode::STR_FROM_INT[int_width],
)
}
Layout::Builtin(Builtin::Float(_float_width)) => {
LayoutRepr::Builtin(Builtin::Float(_float_width)) => {
let (float, float_layout) = load_symbol_and_layout(scope, &args[0]);
let float_width = match layout_interner.get(float_layout) {
Layout::Builtin(Builtin::Float(float_width)) => float_width,
let float_width = match layout_interner.get(float_layout).repr {
LayoutRepr::Builtin(Builtin::Float(float_width)) => float_width,
_ => unreachable!(),
};
@ -871,7 +878,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
&bitcode::STR_FROM_FLOAT[float_width],
)
}
Layout::Builtin(Builtin::Decimal) => dec_to_str(env, num),
LayoutRepr::Builtin(Builtin::Decimal) => dec_to_str(env, num),
_ => unreachable!(),
}
}
@ -897,8 +904,8 @@ pub(crate) fn run_low_level<'a, 'ctx>(
| NumCountOneBits => {
arguments_with_layouts!((arg, arg_layout));
match layout_interner.get(arg_layout) {
Layout::Builtin(arg_builtin) => {
match layout_interner.get(arg_layout).repr {
LayoutRepr::Builtin(arg_builtin) => {
use roc_mono::layout::Builtin::*;
match arg_builtin {
@ -985,10 +992,10 @@ pub(crate) fn run_low_level<'a, 'ctx>(
use inkwell::FloatPredicate;
match (
layout_interner.get(lhs_layout),
layout_interner.get(rhs_layout),
layout_interner.get(lhs_layout).repr,
layout_interner.get(rhs_layout).repr,
) {
(Layout::Builtin(lhs_builtin), Layout::Builtin(rhs_builtin))
(LayoutRepr::Builtin(lhs_builtin), LayoutRepr::Builtin(rhs_builtin))
if lhs_builtin == rhs_builtin =>
{
use roc_mono::layout::Builtin::*;
@ -1141,8 +1148,8 @@ pub(crate) fn run_low_level<'a, 'ctx>(
NumToFloatCast => {
arguments_with_layouts!((arg, arg_layout));
match layout_interner.get(arg_layout) {
Layout::Builtin(Builtin::Int(width)) => {
match layout_interner.get(arg_layout).repr {
LayoutRepr::Builtin(Builtin::Int(width)) => {
// Converting from int to float
let int_val = arg.into_int_value();
let dest =
@ -1158,7 +1165,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
.into()
}
}
Layout::Builtin(Builtin::Float(_)) => {
LayoutRepr::Builtin(Builtin::Float(_)) => {
// Converting from float to float - e.g. F64 to F32, or vice versa
let dest =
basic_type_from_layout(env, layout_interner, layout).into_float_type();
@ -1167,7 +1174,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
.build_float_cast(arg.into_float_value(), dest, "cast_float_to_float")
.into()
}
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
todo!("Support converting Dec values to floats.");
}
other => {
@ -1263,8 +1270,8 @@ pub(crate) fn run_low_level<'a, 'ctx>(
"cast_to_i8_ptr",
);
let value_ptr = match layout_interner.get(data_layout) {
Layout::Union(union_layout)
let value_ptr = match layout_interner.get(data_layout).repr {
LayoutRepr::Union(union_layout)
if union_layout.stores_tag_id_in_pointer(env.target_info) =>
{
tag_pointer_clear_tag_id(env, ptr)
@ -1529,10 +1536,10 @@ pub fn build_num_binop<'a, 'ctx>(
op: LowLevel,
) -> BasicValueEnum<'ctx> {
match (
layout_interner.get(lhs_layout),
layout_interner.get(rhs_layout),
layout_interner.get(lhs_layout).repr,
layout_interner.get(rhs_layout).repr,
) {
(Layout::Builtin(lhs_builtin), Layout::Builtin(rhs_builtin))
(LayoutRepr::Builtin(lhs_builtin), LayoutRepr::Builtin(rhs_builtin))
if lhs_builtin == rhs_builtin =>
{
use roc_mono::layout::Builtin::*;
@ -1975,8 +1982,8 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
NumToFrac => {
// This is an Int, so we need to convert it.
let target_float_type = match layout_interner.get(return_layout) {
Layout::Builtin(Builtin::Float(float_width)) => {
let target_float_type = match layout_interner.get(return_layout).repr {
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
convert::float_type_from_float_width(env, float_width)
}
_ => internal_error!("There can only be floats here!"),
@ -1992,8 +1999,8 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
NumToIntChecked => {
// return_layout : Result N [OutOfBounds]* ~ { result: N, out_of_bounds: bool }
let target_int_width = match layout_interner.get(return_layout) {
Layout::Struct { field_layouts, .. } if field_layouts.len() == 2 => {
let target_int_width = match layout_interner.get(return_layout).repr {
LayoutRepr::Struct { field_layouts, .. } if field_layouts.len() == 2 => {
debug_assert!(matches!(field_layouts[1], Layout::BOOL));
field_layouts[0].to_int_width()
}
@ -2272,8 +2279,8 @@ fn build_float_unary_op<'a, 'ctx>(
NumSqrtUnchecked => env.call_intrinsic(&LLVM_SQRT[float_width], &[arg.into()]),
NumLogUnchecked => env.call_intrinsic(&LLVM_LOG[float_width], &[arg.into()]),
NumToFrac => {
let return_width = match layout_interner.get(layout) {
Layout::Builtin(Builtin::Float(return_width)) => return_width,
let return_width = match layout_interner.get(layout).repr {
LayoutRepr::Builtin(Builtin::Float(return_width)) => return_width,
_ => internal_error!("Layout for returning is not Float : {:?}", layout),
};
match (float_width, return_width) {
@ -2294,8 +2301,8 @@ fn build_float_unary_op<'a, 'ctx>(
}
}
NumCeiling => {
let (return_signed, return_type) = match layout_interner.get(layout) {
Layout::Builtin(Builtin::Int(int_width)) => (
let (return_signed, return_type) = match layout_interner.get(layout).repr {
LayoutRepr::Builtin(Builtin::Int(int_width)) => (
int_width.is_signed(),
convert::int_type_from_int_width(env, int_width),
),
@ -2314,8 +2321,8 @@ fn build_float_unary_op<'a, 'ctx>(
)
}
NumFloor => {
let (return_signed, return_type) = match layout_interner.get(layout) {
Layout::Builtin(Builtin::Int(int_width)) => (
let (return_signed, return_type) = match layout_interner.get(layout).repr {
LayoutRepr::Builtin(Builtin::Int(int_width)) => (
int_width.is_signed(),
convert::int_type_from_int_width(env, int_width),
),
@ -2334,8 +2341,8 @@ fn build_float_unary_op<'a, 'ctx>(
)
}
NumRound => {
let (return_signed, return_type) = match layout_interner.get(layout) {
Layout::Builtin(Builtin::Int(int_width)) => (
let (return_signed, return_type) = match layout_interner.get(layout).repr {
LayoutRepr::Builtin(Builtin::Int(int_width)) => (
int_width.is_signed(),
convert::int_type_from_int_width(env, int_width),
),
@ -2427,12 +2434,12 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
let (function, closure, closure_layout) = function_details!();
match (
layout_interner.get(list_layout),
layout_interner.get(return_layout),
layout_interner.get(list_layout).repr,
layout_interner.get(return_layout).repr,
) {
(
Layout::Builtin(Builtin::List(element_layout)),
Layout::Builtin(Builtin::List(result_layout)),
LayoutRepr::Builtin(Builtin::List(element_layout)),
LayoutRepr::Builtin(Builtin::List(result_layout)),
) => {
let argument_layouts = &[element_layout];
@ -2467,14 +2474,14 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
let (function, closure, closure_layout) = function_details!();
match (
layout_interner.get(list1_layout),
layout_interner.get(list2_layout),
layout_interner.get(return_layout),
layout_interner.get(list1_layout).repr,
layout_interner.get(list2_layout).repr,
layout_interner.get(return_layout).repr,
) {
(
Layout::Builtin(Builtin::List(element1_layout)),
Layout::Builtin(Builtin::List(element2_layout)),
Layout::Builtin(Builtin::List(result_layout)),
LayoutRepr::Builtin(Builtin::List(element1_layout)),
LayoutRepr::Builtin(Builtin::List(element2_layout)),
LayoutRepr::Builtin(Builtin::List(result_layout)),
) => {
let argument_layouts = &[element1_layout, element2_layout];
@ -2513,16 +2520,16 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
let (function, closure, closure_layout) = function_details!();
match (
layout_interner.get(list1_layout),
layout_interner.get(list2_layout),
layout_interner.get(list3_layout),
layout_interner.get(return_layout),
layout_interner.get(list1_layout).repr,
layout_interner.get(list2_layout).repr,
layout_interner.get(list3_layout).repr,
layout_interner.get(return_layout).repr,
) {
(
Layout::Builtin(Builtin::List(element1_layout)),
Layout::Builtin(Builtin::List(element2_layout)),
Layout::Builtin(Builtin::List(element3_layout)),
Layout::Builtin(Builtin::List(result_layout)),
LayoutRepr::Builtin(Builtin::List(element1_layout)),
LayoutRepr::Builtin(Builtin::List(element2_layout)),
LayoutRepr::Builtin(Builtin::List(element3_layout)),
LayoutRepr::Builtin(Builtin::List(result_layout)),
) => {
let argument_layouts = &[element1_layout, element2_layout, element3_layout];
@ -2564,18 +2571,18 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
let (function, closure, closure_layout) = function_details!();
match (
layout_interner.get(list1_layout),
layout_interner.get(list2_layout),
layout_interner.get(list3_layout),
layout_interner.get(list4_layout),
layout_interner.get(return_layout),
layout_interner.get(list1_layout).repr,
layout_interner.get(list2_layout).repr,
layout_interner.get(list3_layout).repr,
layout_interner.get(list4_layout).repr,
layout_interner.get(return_layout).repr,
) {
(
Layout::Builtin(Builtin::List(element1_layout)),
Layout::Builtin(Builtin::List(element2_layout)),
Layout::Builtin(Builtin::List(element3_layout)),
Layout::Builtin(Builtin::List(element4_layout)),
Layout::Builtin(Builtin::List(result_layout)),
LayoutRepr::Builtin(Builtin::List(element1_layout)),
LayoutRepr::Builtin(Builtin::List(element2_layout)),
LayoutRepr::Builtin(Builtin::List(element3_layout)),
LayoutRepr::Builtin(Builtin::List(element4_layout)),
LayoutRepr::Builtin(Builtin::List(result_layout)),
) => {
let argument_layouts = &[
element1_layout,
@ -2621,8 +2628,8 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
let (function, closure, closure_layout) = function_details!();
match layout_interner.get(list_layout) {
Layout::Builtin(Builtin::List(element_layout)) => {
match layout_interner.get(list_layout).repr {
LayoutRepr::Builtin(Builtin::List(element_layout)) => {
use crate::llvm::bitcode::build_compare_wrapper;
let argument_layouts = &[element_layout, element_layout];
@ -2670,8 +2677,11 @@ fn load_symbol_and_lambda_set<'a, 'ctx>(
scope: &Scope<'a, 'ctx>,
symbol: &Symbol,
) -> (BasicValueEnum<'ctx>, LambdaSet<'a>) {
match scope.get(symbol).map(|(l, v)| (layout_interner.get(*l), v)) {
Some((Layout::LambdaSet(lambda_set), ptr)) => (*ptr, lambda_set),
match scope
.get(symbol)
.map(|(l, v)| (layout_interner.get(*l).repr, v))
{
Some((LayoutRepr::LambdaSet(lambda_set), ptr)) => (*ptr, lambda_set),
Some((other, ptr)) => panic!("Not a lambda set: {:?}, {:?}", other, ptr),
None => panic!("There was no entry for {:?} in scope {:?}", symbol, scope),
}

View file

@ -19,7 +19,7 @@ use inkwell::{AddressSpace, IntPredicate};
use roc_module::symbol::Interns;
use roc_module::symbol::Symbol;
use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, UnionLayout,
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout,
};
use super::build::{cast_if_necessary_for_opaque_recursive_pointers, load_roc_value, FunctionSpec};
@ -470,8 +470,8 @@ fn modify_refcount_layout_help<'a, 'ctx>(
None => return,
};
match layout_interner.get(layout) {
Layout::RecursivePointer(rec_layout) => {
match layout_interner.get(layout).repr {
LayoutRepr::RecursivePointer(rec_layout) => {
let layout = rec_layout;
let bt = basic_type_from_layout(env, layout_interner, layout);
@ -525,9 +525,9 @@ fn modify_refcount_layout_build_function<'a, 'ctx>(
mode: Mode,
layout: InLayout<'a>,
) -> Option<FunctionValue<'ctx>> {
use Layout::*;
use LayoutRepr::*;
match layout_interner.get(layout) {
match layout_interner.get(layout).repr {
Builtin(builtin) => {
modify_refcount_builtin(env, layout_interner, layout_ids, mode, layout, &builtin)
}
@ -569,7 +569,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx>(
Some(function)
}
Layout::RecursivePointer(rec_layout) => {
LayoutRepr::RecursivePointer(rec_layout) => {
let layout = rec_layout;
let function = modify_refcount_layout_build_function(
@ -602,14 +602,16 @@ fn modify_refcount_list<'a, 'ctx>(
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
let element_layout = if let Layout::RecursivePointer(rec) = layout_interner.get(element_layout)
{
rec
} else {
element_layout
};
let element_layout =
if let LayoutRepr::RecursivePointer(rec) = layout_interner.get(element_layout).repr {
rec
} else {
element_layout
};
let list_layout = layout_interner.insert(Layout::Builtin(Builtin::List(element_layout)));
let list_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Builtin(Builtin::List(element_layout)),
});
let (_, fn_name) = function_name_from_mode(
layout_ids,
&env.interns,
@ -803,15 +805,18 @@ fn modify_refcount_str_help<'a, 'ctx>(
let parent = fn_val;
let str_type = zig_str_type(env);
let str_wrapper =
if Layout::Builtin(Builtin::Str).is_passed_by_reference(layout_interner, env.target_info) {
env.builder
.new_build_load(str_type, arg_val.into_pointer_value(), "load_str_to_stack")
} else {
// it's already a struct, just do nothing
debug_assert!(arg_val.is_struct_value());
arg_val
};
let str_wrapper = if (Layout {
repr: LayoutRepr::Builtin(Builtin::Str),
})
.is_passed_by_reference(layout_interner, env.target_info)
{
env.builder
.new_build_load(str_type, arg_val.into_pointer_value(), "load_str_to_stack")
} else {
// it's already a struct, just do nothing
debug_assert!(arg_val.is_struct_value());
arg_val
};
let str_wrapper = str_wrapper.into_struct_value();
let capacity = builder
@ -857,7 +862,9 @@ fn modify_refcount_boxed<'a, 'ctx>(
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
let boxed_layout = layout_interner.insert(Layout::Boxed(inner_layout));
let boxed_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Boxed(inner_layout),
});
let (_, fn_name) = function_name_from_mode(
layout_ids,
@ -919,7 +926,9 @@ fn modify_refcount_box_help<'a, 'ctx>(
let boxed = arg_val.into_pointer_value();
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, boxed);
let call_mode = mode_to_call_mode(fn_val, mode);
let boxed_layout = layout_interner.insert(Layout::Boxed(inner_layout));
let boxed_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Boxed(inner_layout),
});
match mode {
Mode::Inc => {
@ -1063,7 +1072,9 @@ fn build_rec_union<'a, 'ctx>(
mode: Mode,
union_layout: UnionLayout<'a>,
) -> FunctionValue<'ctx> {
let layout = layout_interner.insert(Layout::Union(union_layout));
let layout = layout_interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
});
let (_, fn_name) = function_name_from_mode(
layout_ids,
@ -1166,7 +1177,9 @@ fn build_rec_union_help<'a, 'ctx>(
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, value_ptr);
let call_mode = mode_to_call_mode(fn_val, mode);
let layout = layout_interner.insert(Layout::Union(union_layout));
let layout = layout_interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
});
match mode {
Mode::Inc => {
@ -1288,7 +1301,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
let mut deferred_nonrec = Vec::new_in(env.arena);
for (i, field_layout) in field_layouts.iter().enumerate() {
if let Layout::RecursivePointer(_) = layout_interner.get(*field_layout) {
if let LayoutRepr::RecursivePointer(_) = layout_interner.get(*field_layout).repr {
// this field has type `*i64`, but is really a pointer to the data we want
let elem_pointer = env
.builder
@ -1309,7 +1322,9 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
debug_assert!(ptr_as_i64_ptr.is_pointer_value());
// therefore we must cast it to our desired type
let union_layout = layout_interner.insert(Layout::Union(union_layout));
let union_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
});
let union_type = basic_type_from_layout(env, layout_interner, union_layout);
let recursive_field_ptr = cast_basic_basic(env.builder, ptr_as_i64_ptr, union_type);
@ -1347,7 +1362,9 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
match decrement_or_reuse {
DecOrReuse::Reuse => {}
DecOrReuse::Dec => {
let union_layout = layout_interner.insert(Layout::Union(union_layout));
let union_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
});
refcount_ptr.modify(call_mode, union_layout, env, layout_interner);
}
}
@ -1405,7 +1422,9 @@ fn build_rec_union_recursive_decrement<'a, 'ctx>(
// increment/decrement the cons-cell itself
if let DecOrReuse::Dec = decrement_or_reuse {
let union_layout = layout_interner.insert(Layout::Union(union_layout));
let union_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
});
refcount_ptr.modify(call_mode, union_layout, env, layout_interner);
}
}
@ -1465,7 +1484,9 @@ pub fn build_reset<'a, 'ctx>(
) -> FunctionValue<'ctx> {
let mode = Mode::Dec;
let union_layout_in = layout_interner.insert(Layout::Union(union_layout));
let union_layout_in = layout_interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
});
let layout_id = layout_ids.get(Symbol::DEC, &union_layout_in);
let fn_name = layout_id.to_symbol_string(Symbol::DEC, &env.interns);
let fn_name = format!("{}_reset", fn_name);
@ -1561,7 +1582,9 @@ fn build_reuse_rec_union_help<'a, 'ctx>(
env.builder.position_at_end(should_recurse_block);
let layout = layout_interner.insert(Layout::Union(union_layout));
let layout = layout_interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
});
let do_recurse_block = env.context.append_basic_block(parent, "do_recurse");
let no_recurse_block = env.context.append_basic_block(parent, "no_recurse");
@ -1623,7 +1646,9 @@ fn modify_refcount_nonrecursive<'a, 'ctx>(
fields: &'a [&'a [InLayout<'a>]],
) -> FunctionValue<'ctx> {
let union_layout = UnionLayout::NonRecursive(fields);
let layout = layout_interner.insert(Layout::Union(union_layout));
let layout = layout_interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
});
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
@ -1693,7 +1718,9 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx>(
let before_block = env.builder.get_insert_block().expect("to be in a function");
let union_layout = UnionLayout::NonRecursive(tags);
let layout = layout_interner.insert(Layout::Union(union_layout));
let layout = layout_interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
});
let union_struct_type = basic_type_from_layout(env, layout_interner, layout).into_struct_type();
// read the tag_id
@ -1761,7 +1788,9 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx>(
);
for (i, field_layout) in field_layouts.iter().enumerate() {
if let Layout::RecursivePointer(union_layout) = layout_interner.get(*field_layout) {
if let LayoutRepr::RecursivePointer(union_layout) =
layout_interner.get(*field_layout).repr
{
// This field is a pointer to the recursive pointer.
let field_ptr = env
.builder

View file

@ -12,8 +12,8 @@ use roc_mono::ir::{
Param, Proc, ProcLayout, Stmt,
};
use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, TagIdIntType,
UnionLayout,
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, LayoutRepr, STLayoutInterner,
TagIdIntType, UnionLayout,
};
use roc_std::RocDec;
@ -507,9 +507,9 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
let heap_return_ptr_id = LocalId(wrapper_arg_layouts.len() as u32 - 1);
let inner_ret_layout = match wrapper_arg_layouts
.last()
.map(|l| self.layout_interner.get(*l))
.map(|l| self.layout_interner.get(*l).repr)
{
Some(Layout::Boxed(inner)) => WasmLayout::new(self.layout_interner, inner),
Some(LayoutRepr::Boxed(inner)) => WasmLayout::new(self.layout_interner, inner),
x => internal_error!("Higher-order wrapper: invalid return layout {:?}", x),
};
@ -539,8 +539,8 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
continue;
}
let inner_layout = match self.layout_interner.get(*wrapper_arg) {
Layout::Boxed(inner) => inner,
let inner_layout = match self.layout_interner.get(*wrapper_arg).repr {
LayoutRepr::Boxed(inner) => inner,
x => internal_error!("Expected a Boxed layout, got {:?}", x),
};
if self.layout_interner.stack_size(inner_layout) == 0 {
@ -558,8 +558,9 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
if self.layout_interner.stack_size(closure_data_layout) > 0 {
// The closure data exists, and will have been passed in to the wrapper as a
// one-element struct.
let inner_closure_data_layout = match self.layout_interner.get(closure_data_layout) {
Layout::Struct {
let inner_closure_data_layout = match self.layout_interner.get(closure_data_layout).repr
{
LayoutRepr::Struct {
field_layouts: [inner],
..
} => inner,
@ -635,8 +636,8 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
n_inner_args += 1;
}
let inner_layout = match self.layout_interner.get(value_layout) {
Layout::Boxed(inner) => inner,
let inner_layout = match self.layout_interner.get(value_layout).repr {
LayoutRepr::Boxed(inner) => inner,
x => internal_error!("Expected a Boxed layout, got {:?}", x),
};
self.code_builder.get_local(LocalId(1));
@ -664,26 +665,26 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
fn dereference_boxed_value(&mut self, inner: InLayout) {
use Align::*;
match self.layout_interner.get(inner) {
Layout::Builtin(Builtin::Int(IntWidth::U8 | IntWidth::I8)) => {
match self.layout_interner.get(inner).repr {
LayoutRepr::Builtin(Builtin::Int(IntWidth::U8 | IntWidth::I8)) => {
self.code_builder.i32_load8_u(Bytes1, 0);
}
Layout::Builtin(Builtin::Int(IntWidth::U16 | IntWidth::I16)) => {
LayoutRepr::Builtin(Builtin::Int(IntWidth::U16 | IntWidth::I16)) => {
self.code_builder.i32_load16_u(Bytes2, 0);
}
Layout::Builtin(Builtin::Int(IntWidth::U32 | IntWidth::I32)) => {
LayoutRepr::Builtin(Builtin::Int(IntWidth::U32 | IntWidth::I32)) => {
self.code_builder.i32_load(Bytes4, 0);
}
Layout::Builtin(Builtin::Int(IntWidth::U64 | IntWidth::I64)) => {
LayoutRepr::Builtin(Builtin::Int(IntWidth::U64 | IntWidth::I64)) => {
self.code_builder.i64_load(Bytes8, 0);
}
Layout::Builtin(Builtin::Float(FloatWidth::F32)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
self.code_builder.f32_load(Bytes4, 0);
}
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
self.code_builder.f64_load(Bytes8, 0);
}
Layout::Builtin(Builtin::Bool) => {
LayoutRepr::Builtin(Builtin::Bool) => {
self.code_builder.i32_load8_u(Bytes1, 0);
}
_ => {
@ -1442,8 +1443,8 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
storage: &StoredValue,
fields: &'a [Symbol],
) {
match self.layout_interner.get(layout) {
Layout::Struct { .. } => {
match self.layout_interner.get(layout).repr {
LayoutRepr::Struct { .. } => {
match storage {
StoredValue::StackMemory { location, size, .. } => {
if *size > 0 {
@ -1468,7 +1469,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
}
};
}
Layout::LambdaSet(lambdaset) => {
LayoutRepr::LambdaSet(lambdaset) => {
self.expr_struct(sym, lambdaset.runtime_representation(), storage, fields)
}
_ => {
@ -1900,8 +1901,8 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
};
// allocate heap memory and load its data address onto the value stack
let arg_layout = match self.layout_interner.get(layout) {
Layout::Boxed(arg) => arg,
let arg_layout = match self.layout_interner.get(layout).repr {
LayoutRepr::Boxed(arg) => arg,
_ => internal_error!("ExprBox should always produce a Boxed layout"),
};
let (size, alignment) = self.layout_interner.stack_size_and_alignment(arg_layout);

View file

@ -1,5 +1,5 @@
use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_mono::layout::{InLayout, Layout, LayoutInterner, STLayoutInterner, UnionLayout};
use roc_mono::layout::{InLayout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout};
use crate::{PTR_SIZE, PTR_TYPE};
use roc_wasm_module::ValueType;
@ -47,8 +47,8 @@ impl WasmLayout {
let (size, alignment_bytes) = interner.stack_size_and_alignment(layout);
match interner.get(layout) {
Layout::Builtin(Int(int_width)) => {
match interner.get(layout).repr {
LayoutRepr::Builtin(Int(int_width)) => {
use IntWidth::*;
match int_width {
@ -62,9 +62,9 @@ impl WasmLayout {
}
}
Layout::Builtin(Bool) => Self::Primitive(I32, size),
LayoutRepr::Builtin(Bool) => Self::Primitive(I32, size),
Layout::Builtin(Float(float_width)) => {
LayoutRepr::Builtin(Float(float_width)) => {
use FloatWidth::*;
match float_width {
@ -73,32 +73,32 @@ impl WasmLayout {
}
}
Layout::Builtin(Decimal) => Self::StackMemory {
LayoutRepr::Builtin(Decimal) => Self::StackMemory {
size,
alignment_bytes,
format: StackMemoryFormat::Decimal,
},
Layout::LambdaSet(lambda_set) => {
LayoutRepr::LambdaSet(lambda_set) => {
WasmLayout::new(interner, lambda_set.runtime_representation())
}
Layout::Builtin(Str | List(_))
| Layout::Struct { .. }
| Layout::Union(NonRecursive(_)) => Self::StackMemory {
LayoutRepr::Builtin(Str | List(_))
| LayoutRepr::Struct { .. }
| LayoutRepr::Union(NonRecursive(_)) => Self::StackMemory {
size,
alignment_bytes,
format: StackMemoryFormat::DataStructure,
},
Layout::Union(
LayoutRepr::Union(
Recursive(_)
| NonNullableUnwrapped(_)
| NullableWrapped { .. }
| NullableUnwrapped { .. },
)
| Layout::Boxed(_)
| Layout::RecursivePointer(_) => Self::Primitive(PTR_TYPE, PTR_SIZE),
| LayoutRepr::Boxed(_)
| LayoutRepr::RecursivePointer(_) => Self::Primitive(PTR_TYPE, PTR_SIZE),
}
}

View file

@ -6,7 +6,9 @@ use roc_module::low_level::LowLevel;
use roc_module::symbol::Symbol;
use roc_mono::code_gen_help::HelperOp;
use roc_mono::ir::{HigherOrderLowLevel, PassedFunction, ProcLayout};
use roc_mono::layout::{Builtin, FieldOrderHash, InLayout, Layout, LayoutInterner, UnionLayout};
use roc_mono::layout::{
Builtin, FieldOrderHash, InLayout, Layout, LayoutInterner, LayoutRepr, UnionLayout,
};
use roc_mono::low_level::HigherOrder;
use crate::backend::{ProcLookupData, ProcSource, WasmBackend};
@ -237,19 +239,19 @@ impl<'a> LowLevelCall<'a> {
}
StrGetCapacity => self.load_args_and_call_zig(backend, bitcode::STR_CAPACITY),
StrToNum => {
let number_layout = match backend.layout_interner.get(self.ret_layout) {
Layout::Struct { field_layouts, .. } => field_layouts[0],
let number_layout = match backend.layout_interner.get(self.ret_layout).repr {
LayoutRepr::Struct { field_layouts, .. } => field_layouts[0],
_ => {
internal_error!("Unexpected mono layout {:?} for StrToNum", self.ret_layout)
}
};
// match on the return layout to figure out which zig builtin we need
let intrinsic = match backend.layout_interner.get(number_layout) {
Layout::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
Layout::Builtin(Builtin::Float(float_width)) => {
let intrinsic = match backend.layout_interner.get(number_layout).repr {
LayoutRepr::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
&bitcode::STR_TO_FLOAT[float_width]
}
Layout::Builtin(Builtin::Decimal) => bitcode::DEC_FROM_STR,
LayoutRepr::Builtin(Builtin::Decimal) => bitcode::DEC_FROM_STR,
rest => internal_error!("Unexpected layout {:?} for StrToNum", rest),
};
@ -388,32 +390,36 @@ impl<'a> LowLevelCall<'a> {
};
// Byte offsets of each field in the return struct
let (ret_list_offset, ret_elem_offset, elem_layout) = match self.ret_layout_raw {
Layout::Struct {
let (ret_list_offset, ret_elem_offset, elem_layout) = match self.ret_layout_raw.repr
{
LayoutRepr::Struct {
field_layouts: &[f1, f2],
..
} => match (
backend.layout_interner.get(f1),
backend.layout_interner.get(f2),
) {
(Layout::Builtin(Builtin::List(list_elem)), value_layout)
if value_layout == backend.layout_interner.get(list_elem) =>
{
let list_offset = 0;
let elem_offset = Layout::Builtin(Builtin::List(list_elem))
} => {
let l1 = backend.layout_interner.get(f1);
let l2 = backend.layout_interner.get(f2);
match (l1.repr, l2.repr) {
(LayoutRepr::Builtin(Builtin::List(list_elem)), _)
if l2.repr == backend.layout_interner.get(list_elem).repr =>
{
let list_offset = 0;
let elem_offset = Layout {
repr: LayoutRepr::Builtin(Builtin::List(list_elem)),
}
.stack_size(backend.layout_interner, TARGET_INFO);
(list_offset, elem_offset, f2)
(list_offset, elem_offset, f2)
}
(_, LayoutRepr::Builtin(Builtin::List(list_elem)))
if l1.repr == backend.layout_interner.get(list_elem).repr =>
{
let list_offset =
l1.stack_size(backend.layout_interner, TARGET_INFO);
let elem_offset = 0;
(list_offset, elem_offset, f1)
}
_ => internal_error!("Invalid return layout for ListReplaceUnsafe"),
}
(value_layout, Layout::Builtin(Builtin::List(list_elem)))
if value_layout == backend.layout_interner.get(list_elem) =>
{
let list_offset =
value_layout.stack_size(backend.layout_interner, TARGET_INFO);
let elem_offset = 0;
(list_offset, elem_offset, f1)
}
_ => internal_error!("Invalid return layout for ListReplaceUnsafe"),
},
}
_ => internal_error!("Invalid return layout for ListReplaceUnsafe"),
};
@ -691,9 +697,11 @@ impl<'a> LowLevelCall<'a> {
// The refcount function receives a pointer to an element in the list
// This is the same as a Struct containing the element
let in_memory_layout = backend.layout_interner.insert(Layout::Struct {
field_order_hash: FieldOrderHash::from_ordered_fields(&[]),
field_layouts: backend.env.arena.alloc([elem_layout]),
let in_memory_layout = backend.layout_interner.insert(Layout {
repr: LayoutRepr::Struct {
field_order_hash: FieldOrderHash::from_ordered_fields(&[]),
field_layouts: backend.env.arena.alloc([elem_layout]),
},
});
let dec_fn = backend.get_refcount_fn_index(in_memory_layout, HelperOp::Dec);
let dec_fn_ptr = backend.get_fn_ptr(dec_fn);
@ -737,9 +745,11 @@ impl<'a> LowLevelCall<'a> {
// The refcount function receives a pointer to an element in the list
// This is the same as a Struct containing the element
let in_memory_layout = backend.layout_interner.insert(Layout::Struct {
field_order_hash: FieldOrderHash::from_ordered_fields(&[]),
field_layouts: backend.env.arena.alloc([elem_layout]),
let in_memory_layout = backend.layout_interner.insert(Layout {
repr: LayoutRepr::Struct {
field_order_hash: FieldOrderHash::from_ordered_fields(&[]),
field_layouts: backend.env.arena.alloc([elem_layout]),
},
});
let dec_fn = backend.get_refcount_fn_index(in_memory_layout, HelperOp::Dec);
let dec_fn_ptr = backend.get_fn_ptr(dec_fn);
@ -812,11 +822,11 @@ impl<'a> LowLevelCall<'a> {
}
// Num
NumAdd => match self.ret_layout_raw {
Layout::Builtin(Builtin::Int(width)) => {
NumAdd => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_ADD_OR_PANIC_INT[width])
}
Layout::Builtin(Builtin::Float(width)) => match width {
LayoutRepr::Builtin(Builtin::Float(width)) => match width {
FloatWidth::F32 => {
self.load_args(backend);
backend.code_builder.f32_add()
@ -826,14 +836,14 @@ impl<'a> LowLevelCall<'a> {
backend.code_builder.f64_add()
}
},
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
self.load_args_and_call_zig(backend, bitcode::DEC_ADD_OR_PANIC)
}
_ => panic_ret_type(),
},
NumAddWrap => match self.ret_layout_raw {
Layout::Builtin(Builtin::Int(width)) => match width {
NumAddWrap => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Int(width)) => match width {
IntWidth::I128 | IntWidth::U128 => {
// TODO: don't panic
self.load_args_and_call_zig(backend, &bitcode::NUM_ADD_OR_PANIC_INT[width])
@ -852,7 +862,7 @@ impl<'a> LowLevelCall<'a> {
self.wrap_small_int(backend, width);
}
},
Layout::Builtin(Builtin::Float(width)) => match width {
LayoutRepr::Builtin(Builtin::Float(width)) => match width {
FloatWidth::F32 => {
self.load_args(backend);
backend.code_builder.f32_add()
@ -862,7 +872,7 @@ impl<'a> LowLevelCall<'a> {
backend.code_builder.f64_add()
}
},
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
// TODO: don't panic
self.load_args_and_call_zig(backend, bitcode::DEC_ADD_OR_PANIC)
}
@ -872,42 +882,42 @@ impl<'a> LowLevelCall<'a> {
NumToStr => self.num_to_str(backend),
NumAddChecked => {
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
match backend.layout_interner.get(arg_layout) {
Layout::Builtin(Builtin::Int(width)) => {
match backend.layout_interner.get(arg_layout).repr {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_ADD_CHECKED_INT[width])
}
Layout::Builtin(Builtin::Float(width)) => {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_ADD_CHECKED_FLOAT[width])
}
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
self.load_args_and_call_zig(backend, bitcode::DEC_ADD_WITH_OVERFLOW)
}
x => internal_error!("NumAddChecked is not defined for {:?}", x),
}
}
NumAddSaturated => match self.ret_layout_raw {
Layout::Builtin(Builtin::Int(width)) => {
NumAddSaturated => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_ADD_SATURATED_INT[width])
}
Layout::Builtin(Builtin::Float(FloatWidth::F32)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
self.load_args(backend);
backend.code_builder.f32_add()
}
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
self.load_args(backend);
backend.code_builder.f64_add()
}
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
self.load_args_and_call_zig(backend, bitcode::DEC_ADD_SATURATED)
}
_ => panic_ret_type(),
},
NumSub => match self.ret_layout_raw {
Layout::Builtin(Builtin::Int(width)) => {
NumSub => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_SUB_OR_PANIC_INT[width])
}
Layout::Builtin(Builtin::Float(width)) => match width {
LayoutRepr::Builtin(Builtin::Float(width)) => match width {
FloatWidth::F32 => {
self.load_args(backend);
backend.code_builder.f32_sub()
@ -917,14 +927,14 @@ impl<'a> LowLevelCall<'a> {
backend.code_builder.f64_sub()
}
},
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
self.load_args_and_call_zig(backend, bitcode::DEC_SUB_OR_PANIC)
}
_ => panic_ret_type(),
},
NumSubWrap => match self.ret_layout_raw {
Layout::Builtin(Builtin::Int(width)) => match width {
NumSubWrap => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Int(width)) => match width {
IntWidth::I128 | IntWidth::U128 => {
// TODO: don't panic
self.load_args_and_call_zig(backend, &bitcode::NUM_SUB_OR_PANIC_INT[width])
@ -943,7 +953,7 @@ impl<'a> LowLevelCall<'a> {
self.wrap_small_int(backend, width);
}
},
Layout::Builtin(Builtin::Float(width)) => match width {
LayoutRepr::Builtin(Builtin::Float(width)) => match width {
FloatWidth::F32 => {
self.load_args(backend);
backend.code_builder.f32_sub()
@ -953,7 +963,7 @@ impl<'a> LowLevelCall<'a> {
backend.code_builder.f64_sub()
}
},
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
// TODO: don't panic
self.load_args_and_call_zig(backend, bitcode::DEC_SUB_OR_PANIC)
}
@ -961,42 +971,42 @@ impl<'a> LowLevelCall<'a> {
},
NumSubChecked => {
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
match backend.layout_interner.get(arg_layout) {
Layout::Builtin(Builtin::Int(width)) => {
match backend.layout_interner.get(arg_layout).repr {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_SUB_CHECKED_INT[width])
}
Layout::Builtin(Builtin::Float(width)) => {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_SUB_CHECKED_FLOAT[width])
}
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
self.load_args_and_call_zig(backend, bitcode::DEC_SUB_WITH_OVERFLOW)
}
x => internal_error!("NumSubChecked is not defined for {:?}", x),
}
}
NumSubSaturated => match self.ret_layout_raw {
Layout::Builtin(Builtin::Int(width)) => {
NumSubSaturated => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_SUB_SATURATED_INT[width])
}
Layout::Builtin(Builtin::Float(FloatWidth::F32)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
self.load_args(backend);
backend.code_builder.f32_sub()
}
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
self.load_args(backend);
backend.code_builder.f64_sub()
}
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
self.load_args_and_call_zig(backend, bitcode::DEC_SUB_SATURATED)
}
_ => panic_ret_type(),
},
NumMul => match self.ret_layout_raw {
Layout::Builtin(Builtin::Int(width)) => {
NumMul => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_MUL_OR_PANIC_INT[width])
}
Layout::Builtin(Builtin::Float(width)) => match width {
LayoutRepr::Builtin(Builtin::Float(width)) => match width {
FloatWidth::F32 => {
self.load_args(backend);
backend.code_builder.f32_mul()
@ -1006,13 +1016,13 @@ impl<'a> LowLevelCall<'a> {
backend.code_builder.f64_mul()
}
},
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
self.load_args_and_call_zig(backend, bitcode::DEC_MUL_OR_PANIC)
}
_ => panic_ret_type(),
},
NumMulWrap => match self.ret_layout_raw {
Layout::Builtin(Builtin::Int(width)) => match width {
NumMulWrap => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Int(width)) => match width {
IntWidth::I128 | IntWidth::U128 => {
self.load_args_and_call_zig(backend, &bitcode::NUM_MUL_WRAP_INT[width])
}
@ -1030,7 +1040,7 @@ impl<'a> LowLevelCall<'a> {
self.wrap_small_int(backend, width);
}
},
Layout::Builtin(Builtin::Float(width)) => match width {
LayoutRepr::Builtin(Builtin::Float(width)) => match width {
FloatWidth::F32 => {
self.load_args(backend);
backend.code_builder.f32_mul()
@ -1040,25 +1050,25 @@ impl<'a> LowLevelCall<'a> {
backend.code_builder.f64_mul()
}
},
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
// TODO: don't panic
self.load_args_and_call_zig(backend, bitcode::DEC_MUL_OR_PANIC)
}
_ => panic_ret_type(),
},
NumMulSaturated => match self.ret_layout_raw {
Layout::Builtin(Builtin::Int(width)) => {
NumMulSaturated => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_MUL_SATURATED_INT[width])
}
Layout::Builtin(Builtin::Float(FloatWidth::F32)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
self.load_args(backend);
backend.code_builder.f32_mul()
}
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
self.load_args(backend);
backend.code_builder.f64_mul()
}
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
self.load_args_and_call_zig(backend, bitcode::DEC_MUL_SATURATED)
}
_ => panic_ret_type(),
@ -1066,14 +1076,14 @@ impl<'a> LowLevelCall<'a> {
NumMulChecked => {
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
match backend.layout_interner.get(arg_layout) {
Layout::Builtin(Builtin::Int(width)) => {
match backend.layout_interner.get(arg_layout).repr {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_MUL_CHECKED_INT[width])
}
Layout::Builtin(Builtin::Float(width)) => {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_MUL_CHECKED_FLOAT[width])
}
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
self.load_args_and_call_zig(backend, bitcode::DEC_MUL_WITH_OVERFLOW)
}
x => internal_error!("NumMulChecked is not defined for {:?}", x),
@ -1248,8 +1258,8 @@ impl<'a> LowLevelCall<'a> {
x => todo!("{:?} for {:?}", self.lowlevel, x),
}
}
NumDivCeilUnchecked => match self.ret_layout_raw {
Layout::Builtin(Builtin::Int(width)) => {
NumDivCeilUnchecked => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_DIV_CEIL[width])
}
_ => panic_ret_type(),
@ -1459,32 +1469,32 @@ impl<'a> LowLevelCall<'a> {
_ => todo!("{:?} for {:?}", self.lowlevel, self.ret_layout),
}
}
NumSin => match self.ret_layout_raw {
Layout::Builtin(Builtin::Float(width)) => {
NumSin => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_SIN[width]);
}
_ => panic_ret_type(),
},
NumCos => match self.ret_layout_raw {
Layout::Builtin(Builtin::Float(width)) => {
NumCos => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_COS[width]);
}
_ => panic_ret_type(),
},
NumSqrtUnchecked => {
self.load_args(backend);
match self.ret_layout_raw {
Layout::Builtin(Builtin::Float(FloatWidth::F32)) => {
match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
backend.code_builder.f32_sqrt()
}
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
backend.code_builder.f64_sqrt()
}
_ => panic_ret_type(),
}
}
NumLogUnchecked => match self.ret_layout_raw {
Layout::Builtin(Builtin::Float(width)) => {
NumLogUnchecked => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_LOG[width]);
}
_ => panic_ret_type(),
@ -1507,8 +1517,8 @@ impl<'a> LowLevelCall<'a> {
_ => todo!("{:?}: {:?} -> {:?}", self.lowlevel, arg_type, ret_type),
}
}
NumPow => match self.ret_layout_raw {
Layout::Builtin(Builtin::Float(width)) => {
NumPow => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_POW[width]);
}
_ => panic_ret_type(),
@ -1517,8 +1527,9 @@ impl<'a> LowLevelCall<'a> {
NumCountLeadingZeroBits => match backend
.layout_interner
.get(backend.storage.symbol_layouts[&self.arguments[0]])
.repr
{
Layout::Builtin(Builtin::Int(width)) => {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(
backend,
&bitcode::NUM_COUNT_LEADING_ZERO_BITS[width],
@ -1529,8 +1540,9 @@ impl<'a> LowLevelCall<'a> {
NumCountTrailingZeroBits => match backend
.layout_interner
.get(backend.storage.symbol_layouts[&self.arguments[0]])
.repr
{
Layout::Builtin(Builtin::Int(width)) => {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(
backend,
&bitcode::NUM_COUNT_TRAILING_ZERO_BITS[width],
@ -1541,8 +1553,9 @@ impl<'a> LowLevelCall<'a> {
NumCountOneBits => match backend
.layout_interner
.get(backend.storage.symbol_layouts[&self.arguments[0]])
.repr
{
Layout::Builtin(Builtin::Int(width)) => {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_COUNT_ONE_BITS[width]);
}
_ => panic_ret_type(),
@ -1617,20 +1630,20 @@ impl<'a> LowLevelCall<'a> {
NumIsInfinite => num_is_infinite(backend, self.arguments[0]),
NumIsFinite => num_is_finite(backend, self.arguments[0]),
NumAtan => match self.ret_layout_raw {
Layout::Builtin(Builtin::Float(width)) => {
NumAtan => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_ATAN[width]);
}
_ => panic_ret_type(),
},
NumAcos => match self.ret_layout_raw {
Layout::Builtin(Builtin::Float(width)) => {
NumAcos => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_ACOS[width]);
}
_ => panic_ret_type(),
},
NumAsin => match self.ret_layout_raw {
Layout::Builtin(Builtin::Float(width)) => {
NumAsin => match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Float(width)) => {
self.load_args_and_call_zig(backend, &bitcode::NUM_ASIN[width]);
}
_ => panic_ret_type(),
@ -1777,15 +1790,15 @@ impl<'a> LowLevelCall<'a> {
NumIntCast => {
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
let arg_type = CodeGenNumType::from(arg_layout);
let arg_width = match backend.layout_interner.get(arg_layout) {
Layout::Builtin(Builtin::Int(w)) => w,
Layout::Builtin(Builtin::Bool) => IntWidth::U8,
let arg_width = match backend.layout_interner.get(arg_layout).repr {
LayoutRepr::Builtin(Builtin::Int(w)) => w,
LayoutRepr::Builtin(Builtin::Bool) => IntWidth::U8,
x => internal_error!("Num.intCast is not defined for {:?}", x),
};
let ret_type = CodeGenNumType::from(self.ret_layout);
let ret_width = match self.ret_layout_raw {
Layout::Builtin(Builtin::Int(w)) => w,
let ret_width = match self.ret_layout_raw.repr {
LayoutRepr::Builtin(Builtin::Int(w)) => w,
x => internal_error!("Num.intCast is not defined for {:?}", x),
};
@ -1847,10 +1860,10 @@ impl<'a> LowLevelCall<'a> {
NumToFloatCast => {
self.load_args(backend);
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
let arg_signed = match backend.layout_interner.get(arg_layout) {
Layout::Builtin(Builtin::Int(w)) => w.is_signed(),
Layout::Builtin(Builtin::Float(_)) => true, // unused
Layout::Builtin(Builtin::Decimal) => true,
let arg_signed = match backend.layout_interner.get(arg_layout).repr {
LayoutRepr::Builtin(Builtin::Int(w)) => w.is_signed(),
LayoutRepr::Builtin(Builtin::Float(_)) => true, // unused
LayoutRepr::Builtin(Builtin::Decimal) => true,
x => internal_error!("Num.intCast is not defined for {:?}", x),
};
let ret_type = CodeGenNumType::from(self.ret_layout);
@ -1894,24 +1907,18 @@ impl<'a> LowLevelCall<'a> {
NumToIntChecked => {
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
let (arg_width, ret_width) =
match (backend.layout_interner.get(arg_layout), self.ret_layout_raw) {
(
Layout::Builtin(Builtin::Int(arg_width)),
Layout::Struct {
field_layouts: &[ret, ..],
..
},
) => match backend.layout_interner.get(ret) {
Layout::Builtin(Builtin::Int(ret_width)) => (arg_width, ret_width),
_ => {
internal_error!(
"NumToIntChecked is not defined for signature {:?} -> {:?}",
arg_layout,
self.ret_layout
);
}
let (arg_width, ret_width) = match (
backend.layout_interner.get(arg_layout).repr,
self.ret_layout_raw.repr,
) {
(
LayoutRepr::Builtin(Builtin::Int(arg_width)),
LayoutRepr::Struct {
field_layouts: &[ret, ..],
..
},
) => match backend.layout_interner.get(ret).repr {
LayoutRepr::Builtin(Builtin::Int(ret_width)) => (arg_width, ret_width),
_ => {
internal_error!(
"NumToIntChecked is not defined for signature {:?} -> {:?}",
@ -1919,7 +1926,15 @@ impl<'a> LowLevelCall<'a> {
self.ret_layout
);
}
};
},
_ => {
internal_error!(
"NumToIntChecked is not defined for signature {:?} -> {:?}",
arg_layout,
self.ret_layout
);
}
};
if arg_width.is_signed() {
self.load_args_and_call_zig(
@ -2005,12 +2020,12 @@ impl<'a> LowLevelCall<'a> {
let invert_result = matches!(self.lowlevel, LowLevel::NotEq);
match arg_layout_raw {
Layout::Builtin(
match arg_layout_raw.repr {
LayoutRepr::Builtin(
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal,
) => self.eq_or_neq_number(backend),
Layout::Builtin(Builtin::Str) => {
LayoutRepr::Builtin(Builtin::Str) => {
self.load_args_and_call_zig(backend, bitcode::STR_EQUAL);
if invert_result {
backend.code_builder.i32_eqz();
@ -2019,21 +2034,21 @@ impl<'a> LowLevelCall<'a> {
// Empty record is always equal to empty record.
// There are no runtime arguments to check, so just emit true or false.
Layout::Struct { field_layouts, .. } if field_layouts.is_empty() => {
LayoutRepr::Struct { field_layouts, .. } if field_layouts.is_empty() => {
backend.code_builder.i32_const(!invert_result as i32);
}
// Void is always equal to void. This is the type for the contents of the empty list in `[] == []`
// This instruction will never execute, but we need an i32 for module validation
Layout::Union(UnionLayout::NonRecursive(tags)) if tags.is_empty() => {
LayoutRepr::Union(UnionLayout::NonRecursive(tags)) if tags.is_empty() => {
backend.code_builder.i32_const(!invert_result as i32);
}
Layout::Builtin(Builtin::List(_))
| Layout::Struct { .. }
| Layout::Union(_)
| Layout::LambdaSet(_)
| Layout::Boxed(_) => {
LayoutRepr::Builtin(Builtin::List(_))
| LayoutRepr::Struct { .. }
| LayoutRepr::Union(_)
| LayoutRepr::LambdaSet(_)
| LayoutRepr::Boxed(_) => {
// Don't want Zig calling convention here, we're calling internal Roc functions
backend
.storage
@ -2051,7 +2066,7 @@ impl<'a> LowLevelCall<'a> {
}
}
Layout::RecursivePointer(_) => {
LayoutRepr::RecursivePointer(_) => {
internal_error!(
"Tried to apply `==` to RecursivePointer values {:?}",
self.arguments,
@ -2147,11 +2162,11 @@ impl<'a> LowLevelCall<'a> {
fn num_to_str(&self, backend: &mut WasmBackend<'a, '_>) {
let arg_layout = backend.storage.symbol_layouts[&self.arguments[0]];
match backend.layout_interner.get(arg_layout) {
Layout::Builtin(Builtin::Int(width)) => {
match backend.layout_interner.get(arg_layout).repr {
LayoutRepr::Builtin(Builtin::Int(width)) => {
self.load_args_and_call_zig(backend, &bitcode::STR_FROM_INT[width])
}
Layout::Builtin(Builtin::Float(width)) => match width {
LayoutRepr::Builtin(Builtin::Float(width)) => match width {
FloatWidth::F32 => {
self.load_args(backend);
backend.code_builder.f64_promote_f32();
@ -2161,7 +2176,7 @@ impl<'a> LowLevelCall<'a> {
self.load_args_and_call_zig(backend, &bitcode::STR_FROM_FLOAT[width]);
}
},
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
self.load_args_and_call_zig(backend, bitcode::DEC_TO_STR)
}
x => internal_error!("NumToStr is not defined for {:?}", x),
@ -2356,8 +2371,9 @@ pub fn call_higher_order_lowlevel<'a>(
let (closure_data_layout, closure_data_exists) = match backend
.layout_interner
.get(backend.storage.symbol_layouts[captured_environment])
.repr
{
Layout::LambdaSet(lambda_set) => {
LayoutRepr::LambdaSet(lambda_set) => {
if lambda_set.is_represented(backend.layout_interner).is_some() {
(lambda_set.runtime_representation(), true)
} else {
@ -2367,7 +2383,7 @@ pub fn call_higher_order_lowlevel<'a>(
(Layout::UNIT, false)
}
}
Layout::Struct {
LayoutRepr::Struct {
field_layouts: &[], ..
} => (Layout::UNIT, false),
x => internal_error!("Closure data has an invalid layout\n{:?}", x),
@ -2448,10 +2464,12 @@ pub fn call_higher_order_lowlevel<'a>(
argument_layouts.len()
};
let boxed_closure_arg_layouts = argument_layouts
.iter()
.take(n_non_closure_args)
.map(|lay| backend.layout_interner.insert(Layout::Boxed(*lay)));
let boxed_closure_arg_layouts =
argument_layouts.iter().take(n_non_closure_args).map(|lay| {
backend.layout_interner.insert(Layout {
repr: LayoutRepr::Boxed(*lay),
})
});
wrapper_arg_layouts.push(wrapped_captures_layout);
wrapper_arg_layouts.extend(boxed_closure_arg_layouts);
@ -2459,11 +2477,9 @@ pub fn call_higher_order_lowlevel<'a>(
match helper_proc_source {
ProcSource::HigherOrderMapper(_) => {
// Our convention for mappers is that they write to the heap via the last argument
wrapper_arg_layouts.push(
backend
.layout_interner
.insert(Layout::Boxed(*result_layout)),
);
wrapper_arg_layouts.push(backend.layout_interner.insert(Layout {
repr: LayoutRepr::Boxed(*result_layout),
}));
ProcLayout {
arguments: wrapper_arg_layouts.into_bump_slice(),
result: Layout::UNIT,
@ -2592,8 +2608,8 @@ pub fn call_higher_order_lowlevel<'a>(
}
fn unwrap_list_elem_layout(list_layout: Layout) -> InLayout {
match list_layout {
Layout::Builtin(Builtin::List(x)) => x,
match list_layout.repr {
LayoutRepr::Builtin(Builtin::List(x)) => x,
e => internal_error!("expected List layout, got {:?}", e),
}
}
@ -2655,9 +2671,11 @@ fn list_map_n<'a>(
for el in arg_elem_layouts.iter() {
// The dec function will be passed a pointer to the element within the list, not the element itself!
// Here we wrap the layout in a Struct to ensure we get the right code gen
let el_ptr = backend.layout_interner.insert(Layout::Struct {
field_order_hash: FieldOrderHash::from_ordered_fields(&[]),
field_layouts: backend.env.arena.alloc([*el]),
let el_ptr = backend.layout_interner.insert(Layout {
repr: LayoutRepr::Struct {
field_order_hash: FieldOrderHash::from_ordered_fields(&[]),
field_layouts: backend.env.arena.alloc([*el]),
},
});
let idx = backend.get_refcount_fn_index(el_ptr, HelperOp::Dec);
let ptr = backend.get_fn_ptr(idx);
@ -2695,9 +2713,11 @@ fn ensure_symbol_is_in_memory<'a>(
offset,
symbol,
);
let in_memory_layout = backend.layout_interner.insert(Layout::Struct {
field_order_hash: FieldOrderHash::from_ordered_fields(&[]), // don't care
field_layouts: arena.alloc([layout]),
let in_memory_layout = backend.layout_interner.insert(Layout {
repr: LayoutRepr::Struct {
field_order_hash: FieldOrderHash::from_ordered_fields(&[]), // don't care
field_layouts: arena.alloc([layout]),
},
});
(frame_ptr, offset, in_memory_layout)
}

View file

@ -7,7 +7,7 @@ The user needs to analyse the Wasm module's memory to decode the result.
use bumpalo::{collections::Vec, Bump};
use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_mono::layout::{Builtin, InLayout, Layout, LayoutInterner, UnionLayout};
use roc_mono::layout::{Builtin, InLayout, LayoutInterner, LayoutRepr, UnionLayout};
use roc_std::{RocBox, RocDec, RocList, RocOrder, RocResult, RocStr, I128, U128};
use roc_wasm_module::{
linking::SymInfo, linking::WasmObjectSymbol, Align, Export, ExportType, LocalId, Signature,
@ -55,30 +55,30 @@ pub fn insert_wrapper_for_layout<'a>(
}
};
match interner.get(layout) {
Layout::Builtin(Builtin::Int(IntWidth::U8 | IntWidth::I8)) => {
match interner.get(layout).repr {
LayoutRepr::Builtin(Builtin::Int(IntWidth::U8 | IntWidth::I8)) => {
i8::insert_wrapper(arena, module, wrapper_name, main_fn_index);
}
Layout::Builtin(Builtin::Int(IntWidth::U16 | IntWidth::I16)) => {
LayoutRepr::Builtin(Builtin::Int(IntWidth::U16 | IntWidth::I16)) => {
i16::insert_wrapper(arena, module, wrapper_name, main_fn_index);
}
Layout::Builtin(Builtin::Int(IntWidth::U32 | IntWidth::I32)) => {
LayoutRepr::Builtin(Builtin::Int(IntWidth::U32 | IntWidth::I32)) => {
i32::insert_wrapper(arena, module, wrapper_name, main_fn_index);
}
Layout::Builtin(Builtin::Int(IntWidth::U64 | IntWidth::I64)) => {
LayoutRepr::Builtin(Builtin::Int(IntWidth::U64 | IntWidth::I64)) => {
i64::insert_wrapper(arena, module, wrapper_name, main_fn_index);
}
Layout::Builtin(Builtin::Float(FloatWidth::F32)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) => {
f32::insert_wrapper(arena, module, wrapper_name, main_fn_index);
}
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) => {
f64::insert_wrapper(arena, module, wrapper_name, main_fn_index);
}
Layout::Builtin(Builtin::Bool) => {
LayoutRepr::Builtin(Builtin::Bool) => {
bool::insert_wrapper(arena, module, wrapper_name, main_fn_index);
}
Layout::Union(UnionLayout::NonRecursive(_)) => stack_data_structure(),
Layout::Union(_) | Layout::Boxed(_) => {
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => stack_data_structure(),
LayoutRepr::Union(_) | LayoutRepr::Boxed(_) => {
i32::insert_wrapper(arena, module, wrapper_name, main_fn_index);
}
_ => stack_data_structure(),

View file

@ -7,7 +7,7 @@ use crate::ir::{
BranchInfo, Call, CallType, Expr, JoinPointId, Literal, Param, Stmt, UpdateModeId,
};
use crate::layout::{
Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, TagIdIntType, UnionLayout,
InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, TagIdIntType, UnionLayout,
};
use super::{let_lowlevel, CodeGenHelp, Context, LAYOUT_BOOL};
@ -22,30 +22,26 @@ pub fn eq_generic<'a>(
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
) -> Stmt<'a> {
let main_body = match layout_interner.get(layout) {
Layout::Builtin(Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal) => {
use crate::layout::Builtin::*;
use LayoutRepr::*;
let main_body = match layout_interner.get(layout).repr {
Builtin(Int(_) | Float(_) | Bool | Decimal) => {
unreachable!(
"No generated proc for `==`. Use direct code gen for {:?}",
layout
)
}
Layout::Builtin(Builtin::Str) => {
Builtin(Str) => {
unreachable!("No generated helper proc for `==` on Str. Use Zig function.")
}
Layout::Builtin(Builtin::List(elem_layout)) => {
eq_list(root, ident_ids, ctx, layout_interner, elem_layout)
}
Layout::Struct { field_layouts, .. } => {
Builtin(List(elem_layout)) => eq_list(root, ident_ids, ctx, layout_interner, elem_layout),
Struct { field_layouts, .. } => {
eq_struct(root, ident_ids, ctx, layout_interner, field_layouts)
}
Layout::Union(union_layout) => {
eq_tag_union(root, ident_ids, ctx, layout_interner, union_layout)
}
Layout::Boxed(inner_layout) => {
eq_boxed(root, ident_ids, ctx, layout_interner, inner_layout)
}
Layout::LambdaSet(_) => unreachable!("`==` is not defined on functions"),
Layout::RecursivePointer(_) => {
Union(union_layout) => eq_tag_union(root, ident_ids, ctx, layout_interner, union_layout),
Boxed(inner_layout) => eq_boxed(root, ident_ids, ctx, layout_interner, inner_layout),
LambdaSet(_) => unreachable!("`==` is not defined on functions"),
RecursivePointer(_) => {
unreachable!(
"Can't perform `==` on RecursivePointer. Should have been replaced by a tag union."
)
@ -440,7 +436,9 @@ fn eq_tag_union_help<'a>(
if is_non_recursive {
compare_ptr_or_value
} else {
let union_layout = layout_interner.insert(Layout::Union(union_layout));
let union_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
});
let loop_params_iter = operands.iter().map(|arg| Param {
symbol: *arg,
ownership: Ownership::Borrowed,
@ -472,9 +470,12 @@ fn eq_tag_fields<'a>(
) -> Stmt<'a> {
// Find a RecursivePointer to use in the tail recursion loop
// (If there are more than one, the others will use non-tail recursion)
let rec_ptr_index = field_layouts
.iter()
.position(|field| matches!(layout_interner.get(*field), Layout::RecursivePointer(_)));
let rec_ptr_index = field_layouts.iter().position(|field| {
matches!(
layout_interner.get(*field).repr,
LayoutRepr::RecursivePointer(_)
)
});
let (tailrec_index, innermost_stmt) = match rec_ptr_index {
None => {
@ -660,7 +661,9 @@ fn eq_list<'a>(
let arena = root.arena;
// A "Box" layout (heap pointer to a single list element)
let box_layout = layout_interner.insert(Layout::Boxed(elem_layout));
let box_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Boxed(elem_layout),
});
// Compare lengths

View file

@ -10,7 +10,8 @@ use crate::ir::{
Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId,
};
use crate::layout::{
Builtin, InLayout, LambdaName, Layout, LayoutInterner, Niche, STLayoutInterner, UnionLayout,
Builtin, InLayout, LambdaName, Layout, LayoutInterner, LayoutRepr, Niche, STLayoutInterner,
UnionLayout,
};
mod equality;
@ -285,11 +286,13 @@ impl<'a> CodeGenHelp<'a> {
self.debug_recursion_depth += 1;
let layout = if matches!(
layout_interner.get(called_layout),
Layout::RecursivePointer(_)
layout_interner.get(called_layout).repr,
LayoutRepr::RecursivePointer(_)
) {
let union_layout = ctx.recursive_union.unwrap();
layout_interner.insert(Layout::Union(union_layout))
layout_interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
})
} else {
called_layout
};
@ -300,7 +303,9 @@ impl<'a> CodeGenHelp<'a> {
let (ret_layout, arg_layouts): (InLayout<'a>, &'a [InLayout<'a>]) = {
let arg = self.replace_rec_ptr(ctx, layout_interner, layout);
let box_arg = layout_interner.insert(Layout::Boxed(arg));
let box_arg = layout_interner.insert(Layout {
repr: LayoutRepr::Boxed(arg),
});
match ctx.op {
Dec | DecRef(_) => (LAYOUT_UNIT, self.arena.alloc([arg])),
@ -429,12 +434,16 @@ impl<'a> CodeGenHelp<'a> {
}
Dec | DecRef(_) | Reset | ResetRef => self.arena.alloc([roc_value]),
IndirectInc => {
let box_layout = layout_interner.insert(Layout::Boxed(layout));
let box_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Boxed(layout),
});
let inc_amount = (self.layout_isize, ARG_2);
self.arena.alloc([(box_layout, ARG_1), inc_amount])
}
IndirectDec => {
let box_layout = layout_interner.insert(Layout::Boxed(layout));
let box_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Boxed(layout),
});
self.arena.alloc([(box_layout, ARG_1)])
}
Eq => self.arena.alloc([roc_value, (layout, ARG_2)]),
@ -482,7 +491,9 @@ impl<'a> CodeGenHelp<'a> {
niche: Niche::NONE,
},
HelperOp::IndirectInc => {
let box_layout = layout_interner.insert(Layout::Boxed(layout));
let box_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Boxed(layout),
});
ProcLayout {
arguments: self.arena.alloc([box_layout, self.layout_isize]),
@ -491,7 +502,9 @@ impl<'a> CodeGenHelp<'a> {
}
}
HelperOp::IndirectDec => {
let box_layout = layout_interner.insert(Layout::Boxed(layout));
let box_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Boxed(layout),
});
ProcLayout {
arguments: self.arena.alloc([box_layout]),
@ -532,15 +545,15 @@ impl<'a> CodeGenHelp<'a> {
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
) -> InLayout<'a> {
let layout = match layout_interner.get(layout) {
Layout::Builtin(Builtin::List(v)) => {
let repr = match layout_interner.get(layout).repr {
LayoutRepr::Builtin(Builtin::List(v)) => {
let v = self.replace_rec_ptr(ctx, layout_interner, v);
Layout::Builtin(Builtin::List(v))
LayoutRepr::Builtin(Builtin::List(v))
}
Layout::Builtin(_) => return layout,
LayoutRepr::Builtin(_) => return layout,
Layout::Struct {
LayoutRepr::Struct {
field_layouts,
field_order_hash,
} => {
@ -548,13 +561,13 @@ impl<'a> CodeGenHelp<'a> {
for f in field_layouts.iter() {
new_field_layouts.push(self.replace_rec_ptr(ctx, layout_interner, *f));
}
Layout::Struct {
LayoutRepr::Struct {
field_layouts: new_field_layouts.into_bump_slice(),
field_order_hash,
}
}
Layout::Union(UnionLayout::NonRecursive(tags)) => {
LayoutRepr::Union(UnionLayout::NonRecursive(tags)) => {
let mut new_tags = Vec::with_capacity_in(tags.len(), self.arena);
for fields in tags {
let mut new_fields = Vec::with_capacity_in(fields.len(), self.arena);
@ -563,28 +576,28 @@ impl<'a> CodeGenHelp<'a> {
}
new_tags.push(new_fields.into_bump_slice());
}
Layout::Union(UnionLayout::NonRecursive(new_tags.into_bump_slice()))
LayoutRepr::Union(UnionLayout::NonRecursive(new_tags.into_bump_slice()))
}
Layout::Union(_) => {
LayoutRepr::Union(_) => {
// we always fully unroll recursive types. That means tha when we find a
// recursive tag union we can replace it with the layout
return layout;
}
Layout::Boxed(inner) => {
LayoutRepr::Boxed(inner) => {
let inner = self.replace_rec_ptr(ctx, layout_interner, inner);
Layout::Boxed(inner)
LayoutRepr::Boxed(inner)
}
Layout::LambdaSet(lambda_set) => {
LayoutRepr::LambdaSet(lambda_set) => {
return self.replace_rec_ptr(ctx, layout_interner, lambda_set.representation)
}
// This line is the whole point of the function
Layout::RecursivePointer(_) => Layout::Union(ctx.recursive_union.unwrap()),
LayoutRepr::RecursivePointer(_) => LayoutRepr::Union(ctx.recursive_union.unwrap()),
};
layout_interner.insert(layout)
layout_interner.insert(Layout { repr })
}
fn union_tail_recursion_fields(
@ -668,16 +681,22 @@ impl<'a> CallerProc<'a> {
};
let box_capture_layout = if let Some(capture_layout) = capture_layout {
layout_interner.insert(Layout::Boxed(capture_layout))
layout_interner.insert(Layout {
repr: LayoutRepr::Boxed(capture_layout),
})
} else {
layout_interner.insert(Layout::Boxed(Layout::UNIT))
layout_interner.insert(Layout {
repr: LayoutRepr::Boxed(Layout::UNIT),
})
};
let box_argument_layout =
layout_interner.insert(Layout::Boxed(passed_function.argument_layouts[0]));
let box_argument_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Boxed(passed_function.argument_layouts[0]),
});
let box_return_layout =
layout_interner.insert(Layout::Boxed(passed_function.return_layout));
let box_return_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Boxed(passed_function.return_layout),
});
let proc_layout = ProcLayout {
arguments: arena.alloc([box_capture_layout, box_argument_layout, box_return_layout]),
@ -826,22 +845,22 @@ fn layout_needs_helper_proc<'a>(
layout: InLayout<'a>,
op: HelperOp,
) -> bool {
match layout_interner.get(layout) {
Layout::Builtin(Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal) => {
false
}
Layout::Builtin(Builtin::Str) => {
match layout_interner.get(layout).repr {
LayoutRepr::Builtin(
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal,
) => false,
LayoutRepr::Builtin(Builtin::Str) => {
// Str type can use either Zig functions or generated IR, since it's not generic.
// Eq uses a Zig function, refcount uses generated IR.
// Both are fine, they were just developed at different times.
matches!(op, HelperOp::Inc | HelperOp::Dec | HelperOp::DecRef(_))
}
Layout::Builtin(Builtin::List(_)) => true,
Layout::Struct { .. } => true, // note: we do generate a helper for Unit, with just a Stmt::Ret
Layout::Union(UnionLayout::NonRecursive(tags)) => !tags.is_empty(),
Layout::Union(_) => true,
Layout::LambdaSet(_) => true,
Layout::RecursivePointer(_) => false,
Layout::Boxed(_) => true,
LayoutRepr::Builtin(Builtin::List(_)) => true,
LayoutRepr::Struct { .. } => true, // note: we do generate a helper for Unit, with just a Stmt::Ret
LayoutRepr::Union(UnionLayout::NonRecursive(tags)) => !tags.is_empty(),
LayoutRepr::Union(_) => true,
LayoutRepr::LambdaSet(_) => true,
LayoutRepr::RecursivePointer(_) => false,
LayoutRepr::Boxed(_) => true,
}
}

View file

@ -12,7 +12,8 @@ use crate::ir::{
BranchInfo, Call, CallType, Expr, JoinPointId, Literal, ModifyRc, Param, Stmt, UpdateModeId,
};
use crate::layout::{
Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, TagIdIntType, UnionLayout,
Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, TagIdIntType,
UnionLayout,
};
use super::{CodeGenHelp, Context, HelperOp};
@ -74,9 +75,9 @@ pub fn refcount_stmt<'a>(
}
ModifyRc::DecRef(structure) => {
match layout_interner.get(layout) {
match layout_interner.get(layout).repr {
// Str has no children, so Dec is the same as DecRef.
Layout::Builtin(Builtin::Str) => {
LayoutRepr::Builtin(Builtin::Str) => {
ctx.op = HelperOp::Dec;
refcount_stmt(
root,
@ -90,8 +91,8 @@ pub fn refcount_stmt<'a>(
}
// Struct and non-recursive Unions are stack-only, so DecRef is a no-op
Layout::Struct { .. } => following,
Layout::Union(UnionLayout::NonRecursive(_)) => following,
LayoutRepr::Struct { .. } => following,
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => following,
// Inline the refcounting code instead of making a function. Don't iterate fields,
// and replace any return statements with jumps to the `following` statement.
@ -181,14 +182,16 @@ pub fn refcount_generic<'a>(
layout: InLayout<'a>,
structure: Symbol,
) -> Stmt<'a> {
match layout_interner.get(layout) {
Layout::Builtin(Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal) => {
match layout_interner.get(layout).repr {
LayoutRepr::Builtin(
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal,
) => {
// Generate a dummy function that immediately returns Unit
// Some higher-order Zig builtins *always* call an RC function on List elements.
rc_return_stmt(root, ident_ids, ctx)
}
Layout::Builtin(Builtin::Str) => refcount_str(root, ident_ids, ctx),
Layout::Builtin(Builtin::List(elem_layout)) => refcount_list(
LayoutRepr::Builtin(Builtin::Str) => refcount_str(root, ident_ids, ctx),
LayoutRepr::Builtin(Builtin::List(elem_layout)) => refcount_list(
root,
ident_ids,
ctx,
@ -196,7 +199,7 @@ pub fn refcount_generic<'a>(
elem_layout,
structure,
),
Layout::Struct { field_layouts, .. } => refcount_struct(
LayoutRepr::Struct { field_layouts, .. } => refcount_struct(
root,
ident_ids,
ctx,
@ -204,7 +207,7 @@ pub fn refcount_generic<'a>(
field_layouts,
structure,
),
Layout::Union(union_layout) => refcount_union(
LayoutRepr::Union(union_layout) => refcount_union(
root,
ident_ids,
ctx,
@ -213,7 +216,7 @@ pub fn refcount_generic<'a>(
union_layout,
structure,
),
Layout::LambdaSet(lambda_set) => {
LayoutRepr::LambdaSet(lambda_set) => {
let runtime_layout = lambda_set.representation;
refcount_generic(
root,
@ -224,10 +227,10 @@ pub fn refcount_generic<'a>(
structure,
)
}
Layout::RecursivePointer(_) => unreachable!(
LayoutRepr::RecursivePointer(_) => unreachable!(
"We should never call a refcounting helper on a RecursivePointer layout directly"
),
Layout::Boxed(inner_layout) => refcount_boxed(
LayoutRepr::Boxed(inner_layout) => refcount_boxed(
root,
ident_ids,
ctx,
@ -298,15 +301,17 @@ pub fn refcount_reset_proc_body<'a>(
let is_unique = root.create_symbol(ident_ids, "is_unique");
let addr = root.create_symbol(ident_ids, "addr");
let union_layout = match layout_interner.get(layout) {
Layout::Union(u) => u,
let union_layout = match layout_interner.get(layout).repr {
LayoutRepr::Union(u) => u,
_ => unimplemented!("Reset is only implemented for UnionLayout"),
};
// Whenever we recurse into a child layout we will want to Decrement
ctx.op = HelperOp::Dec;
ctx.recursive_union = Some(union_layout);
let recursion_ptr = layout_interner.insert(Layout::RecursivePointer(layout));
let recursion_ptr = layout_interner.insert(Layout {
repr: LayoutRepr::RecursivePointer(layout),
});
// Reset structure is unique. Decrement its children and return a pointer to the allocation.
let then_stmt = {
@ -480,15 +485,17 @@ pub fn refcount_resetref_proc_body<'a>(
let is_unique = root.create_symbol(ident_ids, "is_unique");
let addr = root.create_symbol(ident_ids, "addr");
let union_layout = match layout_interner.get(layout) {
Layout::Union(u) => u,
let union_layout = match layout_interner.get(layout).repr {
LayoutRepr::Union(u) => u,
_ => unimplemented!("Reset is only implemented for UnionLayout"),
};
// Whenever we recurse into a child layout we will want to Decrement
ctx.op = HelperOp::Dec;
ctx.recursive_union = Some(union_layout);
let recursion_ptr = layout_interner.insert(Layout::RecursivePointer(layout));
let recursion_ptr = layout_interner.insert(Layout {
repr: LayoutRepr::RecursivePointer(layout),
});
// Reset structure is unique. Return a pointer to the allocation.
let then_stmt = Stmt::Ret(addr);
@ -859,7 +866,9 @@ fn refcount_list<'a>(
let arena = root.arena;
// A "Box" layout (heap pointer to a single list element)
let box_layout = layout_interner.insert(Layout::Boxed(elem_layout));
let box_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Boxed(elem_layout),
});
//
// Check if the list is empty
@ -1480,8 +1489,10 @@ fn refcount_union_rec<'a>(
};
let rc_structure_stmt = {
let alignment = Layout::Union(union_layout)
.allocation_alignment_bytes(layout_interner, root.target_info);
let alignment = Layout {
repr: LayoutRepr::Union(union_layout),
}
.allocation_alignment_bytes(layout_interner, root.target_info);
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
modify_refcount(
@ -1537,7 +1548,9 @@ fn refcount_union_tailrec<'a>(
let tailrec_loop = JoinPointId(root.create_symbol(ident_ids, "tailrec_loop"));
let current = root.create_symbol(ident_ids, "current");
let next_ptr = root.create_symbol(ident_ids, "next_ptr");
let layout = layout_interner.insert(Layout::Union(union_layout));
let layout = layout_interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
});
let tag_id_layout = union_layout.tag_id_layout();
@ -1682,7 +1695,9 @@ fn refcount_union_tailrec<'a>(
let jump_with_null_ptr = Stmt::Let(
null_pointer,
Expr::NullPointer,
layout_interner.insert(Layout::Union(union_layout)),
layout_interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
}),
root.arena.alloc(Stmt::Jump(
jp_modify_union,
root.arena.alloc([null_pointer]),
@ -1726,7 +1741,9 @@ fn refcount_union_tailrec<'a>(
));
let loop_init = Stmt::Jump(tailrec_loop, root.arena.alloc([initial_structure]));
let union_layout = layout_interner.insert(Layout::Union(union_layout));
let union_layout = layout_interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
});
let loop_param = Param {
symbol: current,
ownership: Ownership::Borrowed,

View file

@ -10,7 +10,8 @@ use crate::{
ModifyRc, Param, Proc, ProcLayout, Stmt,
},
layout::{
Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, TagIdIntType, UnionLayout,
Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, TagIdIntType,
UnionLayout,
},
};
@ -198,8 +199,8 @@ impl<'a, 'r> Ctx<'a, 'r> {
// lazily.
loop {
layout = self.interner.chase_recursive_in(layout);
match self.interner.get(layout) {
Layout::LambdaSet(ls) => layout = ls.representation,
match self.interner.get(layout).repr {
LayoutRepr::LambdaSet(ls) => layout = ls.representation,
_ => return layout,
}
}
@ -291,9 +292,9 @@ impl<'a, 'r> Ctx<'a, 'r> {
} => {
self.check_sym_layout(*cond_symbol, *cond_layout, UseKind::SwitchCond);
let layout = self.resolve(*cond_layout);
match self.interner.get(layout) {
Layout::Builtin(Builtin::Int(_)) => {}
Layout::Builtin(Builtin::Bool) => {}
match self.interner.get(layout).repr {
LayoutRepr::Builtin(Builtin::Int(_)) => {}
LayoutRepr::Builtin(Builtin::Bool) => {}
_ => self.problem(ProblemKind::BadSwitchConditionLayout {
found_layout: *cond_layout,
}),
@ -397,7 +398,9 @@ impl<'a, 'r> Ctx<'a, 'r> {
tag_id,
arguments,
} => {
let interned_layout = self.interner.insert(Layout::Union(tag_layout));
let interned_layout = self.interner.insert(Layout {
repr: LayoutRepr::Union(tag_layout),
});
self.check_tag_expr(interned_layout, tag_layout, tag_id, arguments);
Some(interned_layout)
}
@ -435,10 +438,9 @@ impl<'a, 'r> Ctx<'a, 'r> {
}
}
}
Some(
self.interner
.insert(Layout::Builtin(Builtin::List(*elem_layout))),
)
Some(self.interner.insert(Layout {
repr: LayoutRepr::Builtin(Builtin::List(*elem_layout)),
}))
}
Expr::EmptyArray => {
// TODO don't know what the element layout is
@ -446,12 +448,14 @@ impl<'a, 'r> Ctx<'a, 'r> {
}
&Expr::ExprBox { symbol } => self.with_sym_layout(symbol, |ctx, _def_line, layout| {
let inner = layout;
Some(ctx.interner.insert(Layout::Boxed(inner)))
Some(ctx.interner.insert(Layout {
repr: LayoutRepr::Boxed(inner),
}))
}),
&Expr::ExprUnbox { symbol } => self.with_sym_layout(symbol, |ctx, def_line, layout| {
let layout = ctx.resolve(layout);
match ctx.interner.get(layout) {
Layout::Boxed(inner) => Some(inner),
match ctx.interner.get(layout).repr {
LayoutRepr::Boxed(inner) => Some(inner),
_ => {
ctx.problem(ProblemKind::UnboxNotABox { symbol, def_line });
None
@ -466,7 +470,9 @@ impl<'a, 'r> Ctx<'a, 'r> {
tag_id: _,
arguments: _,
} => {
let union = self.interner.insert(Layout::Union(tag_layout));
let union = self.interner.insert(Layout {
repr: LayoutRepr::Union(tag_layout),
});
self.check_sym_layout(symbol, union, UseKind::TagReuse);
// TODO also check update arguments
Some(union)
@ -489,8 +495,8 @@ impl<'a, 'r> Ctx<'a, 'r> {
fn check_struct_at_index(&mut self, structure: Symbol, index: u64) -> Option<InLayout<'a>> {
self.with_sym_layout(structure, |ctx, def_line, layout| {
let layout = ctx.resolve(layout);
match ctx.interner.get(layout) {
Layout::Struct { field_layouts, .. } => {
match ctx.interner.get(layout).repr {
LayoutRepr::Struct { field_layouts, .. } => {
if index as usize >= field_layouts.len() {
ctx.problem(ProblemKind::StructIndexOOB {
structure,
@ -522,7 +528,9 @@ impl<'a, 'r> Ctx<'a, 'r> {
tag_id: u16,
index: u64,
) -> Option<InLayout<'a>> {
let union = self.interner.insert(Layout::Union(union_layout));
let union = self.interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
});
self.with_sym_layout(structure, |ctx, def_line, _layout| {
ctx.check_sym_layout(structure, union, UseKind::TagExpr);

View file

@ -21,7 +21,9 @@ use crate::ir::{
BranchInfo, Call, CallType, Expr, JoinPointId, Literal, ModifyRc, Proc, ProcLayout, Stmt,
UpdateModeId,
};
use crate::layout::{Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, UnionLayout};
use crate::layout::{
Builtin, InLayout, Layout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout,
};
use bumpalo::Bump;
@ -338,9 +340,9 @@ fn specialize_drops_stmt<'a, 'i>(
let in_layout = environment.get_symbol_layout(symbol);
let runtime_layout = layout_interner.runtime_representation(*in_layout);
let new_dec = match runtime_layout {
let new_dec = match runtime_layout.repr {
// Layout has children, try to inline them.
Layout::Struct { field_layouts, .. } => specialize_struct(
LayoutRepr::Struct { field_layouts, .. } => specialize_struct(
arena,
layout_interner,
ident_ids,
@ -350,7 +352,7 @@ fn specialize_drops_stmt<'a, 'i>(
&mut incremented_children,
continuation,
),
Layout::Union(union_layout) => specialize_union(
LayoutRepr::Union(union_layout) => specialize_union(
arena,
layout_interner,
ident_ids,
@ -360,7 +362,7 @@ fn specialize_drops_stmt<'a, 'i>(
&mut incremented_children,
continuation,
),
Layout::Boxed(_layout) => specialize_boxed(
LayoutRepr::Boxed(_layout) => specialize_boxed(
arena,
layout_interner,
ident_ids,
@ -369,7 +371,7 @@ fn specialize_drops_stmt<'a, 'i>(
symbol,
continuation,
),
Layout::Builtin(Builtin::List(layout)) => specialize_list(
LayoutRepr::Builtin(Builtin::List(layout)) => specialize_list(
arena,
layout_interner,
ident_ids,

View file

@ -4,8 +4,8 @@ use crate::borrow::Ownership;
use crate::ir::literal::{make_num_literal, IntOrFloatValue};
use crate::layout::{
self, Builtin, ClosureCallOptions, ClosureRepresentation, EnumDispatch, InLayout, LambdaName,
LambdaSet, Layout, LayoutCache, LayoutInterner, LayoutProblem, Niche, RawFunctionLayout,
TLLayoutInterner, TagIdIntType, UnionLayout, WrappedVariant,
LambdaSet, Layout, LayoutCache, LayoutInterner, LayoutProblem, LayoutRepr, Niche,
RawFunctionLayout, TLLayoutInterner, TagIdIntType, UnionLayout, WrappedVariant,
};
use bumpalo::collections::{CollectIn, Vec};
use bumpalo::Bump;
@ -1063,8 +1063,12 @@ impl<'a> Procs<'a> {
// anonymous functions cannot reference themselves, therefore cannot be tail-recursive
// EXCEPT when the closure conversion makes it tail-recursive.
let is_self_recursive = match top_level.arguments.last().map(|l| layout_cache.get_in(*l)) {
Some(Layout::LambdaSet(lambda_set)) => lambda_set.contains(name.name()),
let is_self_recursive = match top_level
.arguments
.last()
.map(|l| layout_cache.get_in(*l).repr)
{
Some(LayoutRepr::LambdaSet(lambda_set)) => lambda_set.contains(name.name()),
_ => false,
};
@ -4142,8 +4146,8 @@ pub fn with_hole<'a>(
let interned = layout_cache.from_var(env.arena, var, env.subs).unwrap();
let layout = layout_cache.get_in(interned);
match layout {
Layout::Builtin(Builtin::List(elem_layout)) if elem_layout == Layout::U8 => {
match layout.repr {
LayoutRepr::Builtin(Builtin::List(elem_layout)) if elem_layout == Layout::U8 => {
let mut elements = Vec::with_capacity_in(bytes.len(), env.arena);
for byte in bytes.iter() {
elements.push(ListLiteralElement::Literal(Literal::Byte(*byte)));
@ -4155,7 +4159,7 @@ pub fn with_hole<'a>(
Stmt::Let(assigned, expr, interned, hole)
}
Layout::Builtin(Builtin::Str) => Stmt::Let(
LayoutRepr::Builtin(Builtin::Str) => Stmt::Let(
assigned,
Expr::Literal(Literal::Str(
// This is safe because we ensure the utf8 bytes are valid earlier in the compiler pipeline.
@ -4620,14 +4624,16 @@ pub fn with_hole<'a>(
match opt_elem_layout {
Ok(elem_layout) => {
let expr = Expr::EmptyArray;
let list_layout =
layout_cache.put_in(Layout::Builtin(Builtin::List(elem_layout)));
let list_layout = layout_cache.put_in(Layout {
repr: LayoutRepr::Builtin(Builtin::List(elem_layout)),
});
Stmt::Let(assigned, expr, list_layout, hole)
}
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
let expr = Expr::EmptyArray;
let list_layout =
layout_cache.put_in(Layout::Builtin(Builtin::List(Layout::VOID)));
let list_layout = layout_cache.put_in(Layout {
repr: LayoutRepr::Builtin(Builtin::List(Layout::VOID)),
});
Stmt::Let(assigned, expr, list_layout, hole)
}
Err(LayoutProblem::Erroneous) => panic!("list element is error type"),
@ -4673,7 +4679,9 @@ pub fn with_hole<'a>(
elems: elements.into_bump_slice(),
};
let list_layout = layout_cache.put_in(Layout::Builtin(Builtin::List(elem_layout)));
let list_layout = layout_cache.put_in(Layout {
repr: LayoutRepr::Builtin(Builtin::List(elem_layout)),
});
let stmt = Stmt::Let(assigned, expr, list_layout, hole);
@ -4975,8 +4983,8 @@ pub fn with_hole<'a>(
.from_var(env.arena, record_var, env.subs)
.unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err));
let field_layouts = match layout_cache.get_in(record_layout) {
Layout::Struct { field_layouts, .. } => field_layouts,
let field_layouts = match layout_cache.get_in(record_layout).repr {
LayoutRepr::Struct { field_layouts, .. } => field_layouts,
_ => arena.alloc([record_layout]),
};
@ -6138,8 +6146,8 @@ fn convert_tag_union<'a>(
layout_cache.from_var(env.arena, variant_var, env.subs),
"Wrapped"
);
let union_layout = match layout_cache.interner.chase_recursive(variant_layout) {
Layout::Union(ul) => ul,
let union_layout = match layout_cache.interner.chase_recursive(variant_layout).repr {
LayoutRepr::Union(ul) => ul,
other => internal_error!(
"unexpected layout {:?} for {:?}",
other,
@ -6269,7 +6277,9 @@ fn convert_tag_union<'a>(
}
};
let union_layout = layout_cache.put_in(Layout::Union(union_layout));
let union_layout = layout_cache.put_in(Layout {
repr: LayoutRepr::Union(union_layout),
});
let stmt = Stmt::Let(assigned, tag, union_layout, hole);
let iter = field_symbols_temp
@ -7807,9 +7817,10 @@ fn specialize_symbol<'a>(
// data for a lambda set.
let layout = match raw {
RawFunctionLayout::ZeroArgumentThunk(layout) => layout,
RawFunctionLayout::Function(_, lambda_set, _) => {
layout_cache.put_in(Layout::LambdaSet(lambda_set))
}
RawFunctionLayout::Function(_, lambda_set, _) => layout_cache
.put_in(Layout {
repr: LayoutRepr::LambdaSet(lambda_set),
}),
};
let raw = RawFunctionLayout::ZeroArgumentThunk(layout);
@ -9714,8 +9725,8 @@ where
}
while let Some(layout) = stack.pop() {
match layout {
Layout::Builtin(builtin) => match builtin {
match layout.repr {
LayoutRepr::Builtin(builtin) => match builtin {
Builtin::Int(_)
| Builtin::Float(_)
| Builtin::Bool
@ -9723,7 +9734,7 @@ where
| Builtin::Str => { /* do nothing */ }
Builtin::List(element) => stack.push(layout_interner.get(element)),
},
Layout::Struct { field_layouts, .. } => {
LayoutRepr::Struct { field_layouts, .. } => {
if field_layouts.iter().any(|l| {
layout_interner
.get(*l)
@ -9746,10 +9757,10 @@ where
stack.push(layout_interner.get(*in_layout));
}
}
Layout::Boxed(boxed) => {
LayoutRepr::Boxed(boxed) => {
stack.push(layout_interner.get(boxed));
}
Layout::Union(union_layout) => match union_layout {
LayoutRepr::Union(union_layout) => match union_layout {
UnionLayout::NonRecursive(tags) => {
for in_layout in tags.iter().flat_map(|e| e.iter()) {
stack.push(layout_interner.get(*in_layout));
@ -9779,7 +9790,7 @@ where
}
}
},
Layout::LambdaSet(lambda_set) => {
LayoutRepr::LambdaSet(lambda_set) => {
let raw_function_layout =
RawFunctionLayout::Function(lambda_set.args, lambda_set, lambda_set.ret);
@ -9794,7 +9805,7 @@ where
// TODO: figure out if we need to look at the other layouts
// stack.push(layout_interner.get(lambda_set.ret));
}
Layout::RecursivePointer(_) => {
LayoutRepr::RecursivePointer(_) => {
/* do nothing, we've already generated for this type through the Union(_) */
}
}
@ -9816,12 +9827,14 @@ where
I: LayoutInterner<'a>,
{
let interned_unboxed_struct_layout = layout_interner.insert(*unboxed_struct_layout);
let boxed_struct_layout = Layout::Boxed(interned_unboxed_struct_layout);
let boxed_struct_layout = Layout {
repr: LayoutRepr::Boxed(interned_unboxed_struct_layout),
};
let boxed_struct_layout = layout_interner.insert(boxed_struct_layout);
let mut answer = bumpalo::collections::Vec::with_capacity_in(field_layouts.len(), arena);
let field_layouts = match layout_interner.get(interned_unboxed_struct_layout) {
Layout::Struct { field_layouts, .. } => field_layouts,
let field_layouts = match layout_interner.get(interned_unboxed_struct_layout).repr {
LayoutRepr::Struct { field_layouts, .. } => field_layouts,
other => {
unreachable!(
"{:?} {:?}",
@ -9927,7 +9940,9 @@ where
I: LayoutInterner<'a>,
{
let interned = layout_interner.insert(*unboxed_struct_layout);
let boxed_struct_layout = Layout::Boxed(interned);
let boxed_struct_layout = Layout {
repr: LayoutRepr::Boxed(interned),
};
let boxed_struct_layout = layout_interner.insert(boxed_struct_layout);
let mut answer = bumpalo::collections::Vec::with_capacity_in(field_layouts.len(), arena);

View file

@ -5,8 +5,8 @@ use crate::ir::{
GuardStmtSpec, JoinPointId, Literal, Param, Procs, Stmt,
};
use crate::layout::{
Builtin, InLayout, Layout, LayoutCache, LayoutInterner, TLLayoutInterner, TagIdIntType,
UnionLayout,
Builtin, InLayout, Layout, LayoutCache, LayoutInterner, LayoutRepr, TLLayoutInterner,
TagIdIntType, UnionLayout,
};
use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_collections::all::{MutMap, MutSet};
@ -1015,8 +1015,8 @@ fn to_relevant_branch_help<'a>(
match layout {
UnionLayout::NonRecursive([[arg]])
if matches!(
interner.get(*arg),
Layout::Struct {
interner.get(*arg).repr,
LayoutRepr::Struct {
field_layouts: [_],
..
}
@ -1579,8 +1579,8 @@ fn path_to_expr_help<'a>(
PathInstruction::TagIndex { index, tag_id } => {
let index = *index;
match layout_interner.chase_recursive(layout) {
Layout::Union(union_layout) => {
match layout_interner.chase_recursive(layout).repr {
LayoutRepr::Union(union_layout) => {
let inner_expr = Expr::UnionAtIndex {
tag_id: *tag_id,
structure: symbol,
@ -1600,7 +1600,7 @@ fn path_to_expr_help<'a>(
layout = inner_layout;
}
Layout::Struct { field_layouts, .. } => {
LayoutRepr::Struct { field_layouts, .. } => {
debug_assert!(field_layouts.len() > 1);
let inner_expr = Expr::StructAtIndex {
@ -1632,8 +1632,8 @@ fn path_to_expr_help<'a>(
PathInstruction::ListIndex { index } => {
let list_sym = symbol;
match layout_interner.get(layout) {
Layout::Builtin(Builtin::List(elem_layout)) => {
match layout_interner.get(layout).repr {
LayoutRepr::Builtin(Builtin::List(elem_layout)) => {
let (index_sym, new_stores) = build_list_index_probe(env, list_sym, index);
stores.extend(new_stores);
@ -1679,8 +1679,8 @@ fn test_to_comparison<'a>(
// (e.g. record pattern guard matches)
debug_assert!(union.alternatives.len() > 1);
match layout_interner.chase_recursive(test_layout) {
Layout::Union(union_layout) => {
match layout_interner.chase_recursive(test_layout).repr {
LayoutRepr::Union(union_layout) => {
let lhs = Expr::Literal(Literal::Int((tag_id as i128).to_ne_bytes()));
let rhs = Expr::GetTagId {
@ -1769,8 +1769,8 @@ fn test_to_comparison<'a>(
let list_layout = test_layout;
let list_sym = rhs_symbol;
match layout_interner.get(list_layout) {
Layout::Builtin(Builtin::List(_elem_layout)) => {
match layout_interner.get(list_layout).repr {
LayoutRepr::Builtin(Builtin::List(_elem_layout)) => {
let real_len_expr = Expr::Call(Call {
call_type: CallType::LowLevel {
op: LowLevel::ListLen,
@ -2316,7 +2316,7 @@ fn decide_to_branching<'a>(
// We have learned more about the exact layout of the cond (based on the path)
// but tests are still relative to the original cond symbol
let inner_cond_layout_raw = layout_cache.interner.chase_recursive(inner_cond_layout);
let mut switch = if let Layout::Union(union_layout) = inner_cond_layout_raw {
let mut switch = if let LayoutRepr::Union(union_layout) = inner_cond_layout_raw.repr {
let tag_id_symbol = env.unique_symbol();
let temp = Stmt::Switch {
@ -2338,7 +2338,7 @@ fn decide_to_branching<'a>(
union_layout.tag_id_layout(),
env.arena.alloc(temp),
)
} else if let Layout::Builtin(Builtin::List(_)) = inner_cond_layout_raw {
} else if let LayoutRepr::Builtin(Builtin::List(_)) = inner_cond_layout_raw.repr {
let len_symbol = env.unique_symbol();
let switch = Stmt::Switch {
@ -2396,8 +2396,8 @@ fn boolean_all<'a>(arena: &'a Bump, tests: Vec<(Expr<'a>, Expr<'a>, InLayout<'a>
expr = Expr::RunLowLevel(
LowLevel::And,
arena.alloc([
(test, Layout::Builtin(Builtin::Int1)),
(expr, Layout::Builtin(Builtin::Int1)),
(test, LayoutRepr::Builtin(Builtin::Int1)),
(expr, LayoutRepr::Builtin(Builtin::Int1)),
]),
);
}

View file

@ -4,7 +4,7 @@ use roc_error_macros::internal_error;
use roc_module::symbol::Symbol;
use roc_std::RocDec;
use crate::layout::{Builtin, InLayout, Layout, LayoutInterner, TLLayoutInterner};
use crate::layout::{Builtin, InLayout, LayoutInterner, LayoutRepr, TLLayoutInterner};
use super::pattern::Pattern;
@ -83,22 +83,22 @@ pub fn make_num_literal<'a>(
num_str: &str,
num_value: IntOrFloatValue,
) -> NumLiteral {
match interner.get(layout) {
Layout::Builtin(Builtin::Int(width)) => match num_value {
match interner.get(layout).repr {
LayoutRepr::Builtin(Builtin::Int(width)) => match num_value {
IntOrFloatValue::Int(IntValue::I128(n)) => NumLiteral::Int(n, width),
IntOrFloatValue::Int(IntValue::U128(n)) => NumLiteral::U128(n),
IntOrFloatValue::Float(..) => {
internal_error!("Float value where int was expected, should have been a type error")
}
},
Layout::Builtin(Builtin::Float(width)) => match num_value {
LayoutRepr::Builtin(Builtin::Float(width)) => match num_value {
IntOrFloatValue::Float(n) => NumLiteral::Float(n, width),
IntOrFloatValue::Int(int_value) => match int_value {
IntValue::I128(n) => NumLiteral::Float(i128::from_ne_bytes(n) as f64, width),
IntValue::U128(n) => NumLiteral::Float(u128::from_ne_bytes(n) as f64, width),
},
},
Layout::Builtin(Builtin::Decimal) => {
LayoutRepr::Builtin(Builtin::Decimal) => {
let dec = match RocDec::from_str(num_str) {
Some(d) => d,
None => internal_error!(

View file

@ -1,7 +1,7 @@
use crate::ir::{substitute_in_exprs, Env, Expr, Procs, Stmt};
use crate::layout::{
self, Builtin, InLayout, Layout, LayoutCache, LayoutInterner, LayoutProblem, TagIdIntType,
UnionLayout, WrappedVariant,
self, Builtin, InLayout, Layout, LayoutCache, LayoutInterner, LayoutProblem, LayoutRepr,
TagIdIntType, UnionLayout, WrappedVariant,
};
use bumpalo::collections::Vec;
use roc_builtins::bitcode::{FloatWidth, IntWidth};
@ -344,8 +344,8 @@ fn from_can_pattern_help<'a>(
StrLiteral(v) => Ok(Pattern::StrLiteral(v.clone())),
SingleQuote(var, _, c, _) => {
let layout = layout_cache.from_var(env.arena, *var, env.subs);
match layout.map(|l| layout_cache.get_in(l)) {
Ok(Layout::Builtin(Builtin::Int(width))) => {
match layout.map(|l| layout_cache.get_in(l).repr) {
Ok(LayoutRepr::Builtin(Builtin::Int(width))) => {
Ok(Pattern::IntLiteral((*c as i128).to_ne_bytes(), width))
}
o => internal_error!("an integer width was expected, but we found {:?}", o),
@ -583,11 +583,12 @@ fn from_can_pattern_help<'a>(
// problems down the line because we hash layouts and an unrolled
// version is not the same as the minimal version.
let whole_var_layout = layout_cache.from_var(env.arena, *whole_var, env.subs);
let layout =
match whole_var_layout.map(|l| layout_cache.interner.chase_recursive(l)) {
Ok(Layout::Union(ul)) => ul,
_ => internal_error!(),
};
let layout = match whole_var_layout
.map(|l| layout_cache.interner.chase_recursive(l).repr)
{
Ok(LayoutRepr::Union(ul)) => ul,
_ => internal_error!(),
};
use WrappedVariant::*;
match variant {
@ -1551,9 +1552,11 @@ fn store_tag_pattern<'a>(
for (index, (argument, arg_layout)) in arguments.iter().enumerate().rev() {
let mut arg_layout = *arg_layout;
if let Layout::RecursivePointer(_) = layout_cache.get_in(arg_layout) {
if let LayoutRepr::RecursivePointer(_) = layout_cache.get_in(arg_layout).repr {
// TODO(recursive-layouts): fix after disjoint rec ptrs
arg_layout = layout_cache.put_in(Layout::Union(union_layout));
arg_layout = layout_cache.put_in(Layout {
repr: LayoutRepr::Union(union_layout),
});
}
let load = Expr::UnionAtIndex {
@ -1629,7 +1632,7 @@ fn store_newtype_pattern<'a>(
for (index, (argument, arg_layout)) in arguments.iter().enumerate().rev() {
let mut arg_layout = *arg_layout;
if let Layout::RecursivePointer(_) = layout_cache.get_in(arg_layout) {
if let LayoutRepr::RecursivePointer(_) = layout_cache.get_in(arg_layout).repr {
arg_layout = layout;
}

View file

@ -681,9 +681,14 @@ impl FieldOrderHash {
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Layout<'a> {
pub repr: LayoutRepr<'a>,
}
/// Types for code gen must be monomorphic. No type variables allowed!
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum Layout<'a> {
pub enum LayoutRepr<'a> {
Builtin(Builtin<'a>),
Struct {
/// Two different struct types can have the same layout, for example
@ -906,8 +911,10 @@ impl<'a> UnionLayout<'a> {
};
// TODO(recursive-layouts): simplify after we have disjoint recursive pointers
if let Layout::RecursivePointer(_) = interner.get(result) {
interner.insert(Layout::Union(self))
if let LayoutRepr::RecursivePointer(_) = interner.get(result).repr {
interner.insert(Layout {
repr: LayoutRepr::Union(self),
})
} else {
result
}
@ -1453,8 +1460,8 @@ impl<'a> LambdaSet<'a> {
None
} else {
let repr = self.representation;
match interner.get(repr) {
Layout::Struct {
match interner.get(repr).repr {
LayoutRepr::Struct {
field_layouts: &[], ..
} => None,
_ => Some(repr),
@ -1569,10 +1576,10 @@ impl<'a> LambdaSet<'a> {
return ClosureRepresentation::UnwrappedCapture(self.representation);
}
let repr = interner.chase_recursive(self.representation);
let repr_layout = interner.chase_recursive(self.representation);
match repr {
Layout::Union(union) => {
match repr_layout.repr {
LayoutRepr::Union(union) => {
// here we rely on the fact that a union in a closure would be stored in a one-element record.
// a closure representation that is itself union must be a of the shape `Closure1 ... | Closure2 ...`
match union {
@ -1655,7 +1662,7 @@ impl<'a> LambdaSet<'a> {
UnionLayout::NonNullableUnwrapped(_) => internal_error!("I thought a non-nullable-unwrapped variant for a lambda set was impossible: how could such a lambda set be created without a base case?"),
}
}
Layout::Struct { .. } => {
LayoutRepr::Struct { .. } => {
debug_assert_eq!(self.set.len(), 1);
// get the fields from the set, where they are sorted in alphabetic order
@ -1671,8 +1678,8 @@ impl<'a> LambdaSet<'a> {
layout => {
debug_assert!(self.has_enum_dispatch_repr());
let enum_repr = match layout {
Layout::Builtin(Builtin::Bool) => EnumDispatch::Bool,
Layout::Builtin(Builtin::Int(IntWidth::U8)) => EnumDispatch::U8,
LayoutRepr::Builtin(Builtin::Bool) => EnumDispatch::Bool,
LayoutRepr::Builtin(Builtin::Int(IntWidth::U8)) => EnumDispatch::U8,
other => internal_error!("Invalid layout for enum dispatch: {:?}", other),
};
ClosureRepresentation::EnumDispatch(enum_repr)
@ -1696,17 +1703,17 @@ impl<'a> LambdaSet<'a> {
return ClosureCallOptions::UnwrappedCapture(self.representation);
}
let repr = interner.chase_recursive(self.representation);
let repr_layout = interner.chase_recursive(self.representation);
match repr {
Layout::Union(union_layout) => {
if repr == Layout::VOID_NAKED {
match repr_layout.repr {
LayoutRepr::Union(union_layout) => {
if repr_layout == Layout::VOID_NAKED {
debug_assert!(self.set.is_empty());
return ClosureCallOptions::Void;
}
ClosureCallOptions::Union(union_layout)
}
Layout::Struct {
LayoutRepr::Struct {
field_layouts,
field_order_hash,
} => {
@ -1719,8 +1726,8 @@ impl<'a> LambdaSet<'a> {
layout => {
debug_assert!(self.has_enum_dispatch_repr());
let enum_repr = match layout {
Layout::Builtin(Builtin::Bool) => EnumDispatch::Bool,
Layout::Builtin(Builtin::Int(IntWidth::U8)) => EnumDispatch::U8,
LayoutRepr::Builtin(Builtin::Bool) => EnumDispatch::Bool,
LayoutRepr::Builtin(Builtin::Int(IntWidth::U8)) => EnumDispatch::U8,
other => internal_error!("Invalid layout for enum dispatch: {:?}", other),
};
ClosureCallOptions::EnumDispatch(enum_repr)
@ -1791,8 +1798,8 @@ impl<'a> LambdaSet<'a> {
Cacheable(result, criteria)
});
match result.map(|l| env.cache.interner.chase_recursive(l)) {
Ok(Layout::LambdaSet(lambda_set)) => Cacheable(Ok(lambda_set), criteria),
match result.map(|l| env.cache.interner.chase_recursive(l).repr) {
Ok(LayoutRepr::LambdaSet(lambda_set)) => Cacheable(Ok(lambda_set), criteria),
Err(err) => Cacheable(Err(err), criteria),
Ok(layout) => internal_error!("other layout found for lambda set: {:?}", layout),
}
@ -2169,8 +2176,8 @@ pub enum Builtin<'a> {
#[macro_export]
macro_rules! list_element_layout {
($interner:expr, $list_layout:expr) => {
match $interner.get($list_layout) {
Layout::Builtin(Builtin::List(list_layout)) => list_layout,
match $interner.get($list_layout).repr {
LayoutRepr::Builtin(Builtin::List(list_layout)) => list_layout,
_ => internal_error!("invalid list layout"),
}
};
@ -2475,9 +2482,9 @@ impl<'a> Layout<'a> {
where
I: LayoutInterner<'a>,
{
use Layout::*;
use LayoutRepr::*;
match self {
match self.repr {
Builtin(builtin) => builtin.safe_to_memcpy(),
Struct { field_layouts, .. } => field_layouts
.iter()
@ -2521,8 +2528,8 @@ impl<'a> Layout<'a> {
where
I: LayoutInterner<'a>,
{
match self {
Layout::Builtin(builtin) => {
match self.repr {
LayoutRepr::Builtin(builtin) => {
use Builtin::*;
match target_info.ptr_width() {
@ -2536,8 +2543,8 @@ impl<'a> Layout<'a> {
}
}
}
Layout::Union(UnionLayout::NonRecursive(_)) => true,
Layout::LambdaSet(lambda_set) => interner
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => true,
LayoutRepr::LambdaSet(lambda_set) => interner
.get(lambda_set.runtime_representation())
.is_passed_by_reference(interner, target_info),
_ => false,
@ -2570,14 +2577,14 @@ impl<'a> Layout<'a> {
where
I: LayoutInterner<'a>,
{
use Layout::*;
use LayoutRepr::*;
match self {
match self.repr {
Builtin(builtin) => builtin.stack_size(target_info),
Struct { field_layouts, .. } => {
let mut sum = 0;
for field_layout in *field_layouts {
for field_layout in field_layouts {
sum += interner
.get(*field_layout)
.stack_size(interner, target_info);
@ -2598,14 +2605,15 @@ impl<'a> Layout<'a> {
where
I: LayoutInterner<'a>,
{
match self {
Layout::Struct { field_layouts, .. } => field_layouts
use LayoutRepr::*;
match self.repr {
Struct { field_layouts, .. } => field_layouts
.iter()
.map(|x| interner.get(*x).alignment_bytes(interner, target_info))
.max()
.unwrap_or(0),
Layout::Union(variant) => {
Union(variant) => {
use UnionLayout::*;
match variant {
@ -2637,12 +2645,12 @@ impl<'a> Layout<'a> {
| NonNullableUnwrapped(_) => target_info.ptr_width() as u32,
}
}
Layout::LambdaSet(lambda_set) => interner
LambdaSet(lambda_set) => interner
.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::Boxed(_) => target_info.ptr_width() as u32,
Builtin(builtin) => builtin.alignment_bytes(target_info),
RecursivePointer(_) => target_info.ptr_width() as u32,
Boxed(_) => target_info.ptr_width() as u32,
}
}
@ -2652,21 +2660,20 @@ impl<'a> Layout<'a> {
{
let ptr_width = target_info.ptr_width() as u32;
match self {
Layout::Builtin(builtin) => builtin.allocation_alignment_bytes(interner, target_info),
Layout::Struct { .. } => self.alignment_bytes(interner, target_info).max(ptr_width),
Layout::Union(union_layout) => {
union_layout.allocation_alignment_bytes(interner, target_info)
}
Layout::LambdaSet(lambda_set) => interner
use LayoutRepr::*;
match self.repr {
Builtin(builtin) => builtin.allocation_alignment_bytes(interner, target_info),
Struct { .. } => self.alignment_bytes(interner, target_info).max(ptr_width),
Union(union_layout) => union_layout.allocation_alignment_bytes(interner, target_info),
LambdaSet(lambda_set) => interner
.get(lambda_set.runtime_representation())
.allocation_alignment_bytes(interner, target_info),
Layout::RecursivePointer(_) => {
RecursivePointer(_) => {
unreachable!("should be looked up to get an actual layout")
}
Layout::Boxed(inner) => Ord::max(
Boxed(inner) => Ord::max(
ptr_width,
interner.get(*inner).alignment_bytes(interner, target_info),
interner.get(inner).alignment_bytes(interner, target_info),
),
}
}
@ -2702,9 +2709,9 @@ impl<'a> Layout<'a> {
pub fn is_refcounted(&self) -> bool {
use self::Builtin::*;
use Layout::*;
use LayoutRepr::*;
match self {
match self.repr {
Union(UnionLayout::NonRecursive(_)) => false,
Union(_) => true,
@ -2724,9 +2731,9 @@ impl<'a> Layout<'a> {
where
I: LayoutInterner<'a>,
{
use Layout::*;
use LayoutRepr::*;
match self {
match self.repr {
Builtin(builtin) => builtin.is_refcounted(),
Struct { field_layouts, .. } => field_layouts
.iter()
@ -2761,22 +2768,26 @@ impl<'a> Layout<'a> {
stack.push(self);
use LayoutRepr::*;
while let Some(layout) = stack.pop() {
match layout {
Layout::Builtin(builtin) => match builtin {
Builtin::Int(_)
| Builtin::Float(_)
| Builtin::Bool
| Builtin::Decimal
| Builtin::Str
// If there's any layer of indirection (behind a pointer), then it doesn't vary!
| Builtin::List(_) => { /* do nothing */ }
},
match layout.repr {
Builtin(builtin) => {
use self::Builtin::*;
match builtin {
Int(_)
| Float(_)
| Bool
| Decimal
| Str
// If there's any layer of indirection (behind a pointer), then it doesn't vary!
| List(_) => { /* do nothing */ }
}
}
// If there's any layer of indirection (behind a pointer), then it doesn't vary!
Layout::Struct { field_layouts, .. } => {
Struct { field_layouts, .. } => {
stack.extend(field_layouts.iter().map(|interned| interner.get(*interned)))
}
Layout::Union(tag_union) => match tag_union {
Union(tag_union) => match tag_union {
UnionLayout::NonRecursive(tags) | UnionLayout::Recursive(tags) => {
for tag in tags {
stack.extend(tag.iter().map(|interned| interner.get(*interned)));
@ -2794,11 +2805,11 @@ impl<'a> Layout<'a> {
stack.extend(other_fields.iter().map(|interned| interner.get(*interned)));
}
},
Layout::LambdaSet(_) => return true,
Layout::Boxed(_) => {
LambdaSet(_) => return true,
Boxed(_) => {
// If there's any layer of indirection (behind a pointer), then it doesn't vary!
}
Layout::RecursivePointer(_) => {
RecursivePointer(_) => {
/* do nothing, we've already generated for this type through the Union(_) */
}
}
@ -2812,9 +2823,11 @@ impl<'a> Layout<'a> {
if field_layouts.is_empty() {
Self::UNIT_NAKED
} else {
Self::Struct {
field_layouts,
field_order_hash: FieldOrderHash::IRRELEVANT_NON_ZERO_FIELD_HASH,
Self {
repr: LayoutRepr::Struct {
field_layouts,
field_order_hash: FieldOrderHash::IRRELEVANT_NON_ZERO_FIELD_HASH,
},
}
}
}
@ -2823,9 +2836,10 @@ impl<'a> Layout<'a> {
where
I: LayoutInterner<'a>,
{
match self {
Layout::LambdaSet(lambda_set) => interner.get(lambda_set.runtime_representation()),
other => *other,
use LayoutRepr::*;
match self.repr {
LambdaSet(lambda_set) => interner.get(lambda_set.runtime_representation()),
_ => *self,
}
}
@ -2833,8 +2847,9 @@ impl<'a> Layout<'a> {
where
I: LayoutInterner<'a>,
{
match interner.get(layout) {
Layout::LambdaSet(lambda_set) => lambda_set.runtime_representation(),
use LayoutRepr::*;
match interner.get(layout).repr {
LambdaSet(lambda_set) => lambda_set.runtime_representation(),
_ => layout,
}
}
@ -2893,8 +2908,8 @@ impl<'a> Layout<'a> {
pub fn is_recursive_tag_union(self) -> bool {
matches!(
self,
Layout::Union(
self.repr,
LayoutRepr::Union(
UnionLayout::NullableUnwrapped { .. }
| UnionLayout::Recursive(_)
| UnionLayout::NullableWrapped { .. }
@ -3153,7 +3168,9 @@ fn layout_from_flat_type<'a>(
let inner_var = args[0];
let inner_layout =
cached!(Layout::from_var(env, inner_var), criteria, env.subs);
let boxed_layout = env.cache.put_in(Layout::Boxed(inner_layout));
let boxed_layout = env.cache.put_in(Layout {
repr: LayoutRepr::Boxed(inner_layout),
});
Cacheable(Ok(boxed_layout), criteria)
}
@ -3233,9 +3250,11 @@ fn layout_from_flat_type<'a>(
Ok(sortables.pop().unwrap().1)
} else {
let layouts = Vec::from_iter_in(sortables.into_iter().map(|t| t.1), arena);
let struct_layout = Layout::Struct {
field_order_hash,
field_layouts: layouts.into_bump_slice(),
let struct_layout = Layout {
repr: LayoutRepr::Struct {
field_order_hash,
field_layouts: layouts.into_bump_slice(),
},
};
Ok(env.cache.put_in(struct_layout))
@ -3280,9 +3299,11 @@ fn layout_from_flat_type<'a>(
Ok(sortables.pop().unwrap().1)
} else {
let layouts = Vec::from_iter_in(sortables.into_iter().map(|t| t.1), arena);
let struct_layout = Layout::Struct {
field_order_hash,
field_layouts: layouts.into_bump_slice(),
let struct_layout = Layout {
repr: LayoutRepr::Struct {
field_order_hash,
field_layouts: layouts.into_bump_slice(),
},
};
Ok(env.cache.put_in(struct_layout))
@ -4135,8 +4156,11 @@ where
let mut tag_layouts = Vec::with_capacity_in(tags.len(), env.arena);
tag_layouts.extend(tags.iter().map(|r| r.1));
let layout =
Layout::Union(UnionLayout::NonRecursive(tag_layouts.into_bump_slice()));
let layout = Layout {
repr: LayoutRepr::Union(UnionLayout::NonRecursive(
tag_layouts.into_bump_slice(),
)),
};
env.cache.put_in(layout)
}
@ -4247,12 +4271,17 @@ where
};
let union_layout = if criteria.has_naked_recursion_pointer {
env.cache
.interner
.insert_recursive(env.arena, Layout::Union(union_layout))
env.cache.interner.insert_recursive(
env.arena,
Layout {
repr: LayoutRepr::Union(union_layout),
},
)
} else {
// There are no naked recursion pointers, so we can insert the layout as-is.
env.cache.interner.insert(Layout::Union(union_layout))
env.cache.interner.insert(Layout {
repr: LayoutRepr::Union(union_layout),
})
};
criteria.pass_through_recursive_union(rec_var);
@ -4385,9 +4414,9 @@ pub(crate) fn list_layout_from_elem<'a>(
cached!(Layout::from_var(env, element_var), criteria, env.subs)
};
let list_layout = env
.cache
.put_in(Layout::Builtin(Builtin::List(element_layout)));
let list_layout = env.cache.put_in(Layout {
repr: LayoutRepr::Builtin(Builtin::List(element_layout)),
});
Cacheable(Ok(list_layout), criteria)
}
@ -4562,10 +4591,14 @@ mod test {
};
let a = &[Layout::UNIT] as &[_];
let b = &[interner.insert(Layout::LambdaSet(lambda_set))] as &[_];
let b = &[interner.insert(Layout {
repr: LayoutRepr::LambdaSet(lambda_set),
})] as &[_];
let tt = [a, b];
let layout = Layout::Union(UnionLayout::NonRecursive(&tt));
let layout = Layout {
repr: LayoutRepr::Union(UnionLayout::NonRecursive(&tt)),
};
let target_info = TargetInfo::default_x86_64();
assert_eq!(layout.stack_size(&interner, target_info), 1);
@ -4576,11 +4609,15 @@ mod test {
fn memcpy_size_result_u32_unit() {
let mut interner = STLayoutInterner::with_capacity(4, TargetInfo::default_x86_64());
let ok_tag = &[interner.insert(Layout::Builtin(Builtin::Int(IntWidth::U32)))];
let ok_tag = &[interner.insert(Layout {
repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U32)),
})];
let err_tag = &[Layout::UNIT];
let tags = [ok_tag as &[_], err_tag as &[_]];
let union_layout = UnionLayout::NonRecursive(&tags as &[_]);
let layout = Layout::Union(union_layout);
let layout = Layout {
repr: LayoutRepr::Union(union_layout),
};
let target_info = TargetInfo::default_x86_64();
assert_eq!(

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

View file

@ -10,7 +10,7 @@ use crate::ir::{
BranchInfo, Expr, JoinPointId, ModifyRc, Param, Proc, ProcLayout, Stmt, UpdateModeId,
UpdateModeIds,
};
use crate::layout::{InLayout, Layout, LayoutInterner, STLayoutInterner, UnionLayout};
use crate::layout::{InLayout, LayoutInterner, LayoutRepr, STLayoutInterner, UnionLayout};
use bumpalo::Bump;
@ -1133,8 +1133,8 @@ fn symbol_layout_reusability<'a>(
symbol: &Symbol,
layout: &InLayout<'a>,
) -> Reuse {
match layout_interner.get(*layout) {
Layout::Union(union_layout) => {
match layout_interner.get(*layout).repr {
LayoutRepr::Union(union_layout) => {
can_reuse_union_layout_tag(&union_layout, environment.get_symbol_tag(symbol))
}
// Strings literals are constants.

View file

@ -10,7 +10,7 @@ use crate::helpers::wasm::assert_evals_to;
#[cfg(test)]
use indoc::indoc;
use roc_mono::layout::STLayoutInterner;
use roc_mono::layout::{LayoutRepr, STLayoutInterner};
#[cfg(test)]
use roc_std::{RocList, RocStr, U128};
@ -25,7 +25,9 @@ fn width_and_alignment_u8_u8() {
let t = &[Layout::U8] as &[_];
let tt = [t, t];
let layout = Layout::Union(UnionLayout::NonRecursive(&tt));
let layout = Layout {
repr: LayoutRepr::Union(UnionLayout::NonRecursive(&tt)),
};
assert_eq!(layout.alignment_bytes(&interner, target_info), 1);
assert_eq!(layout.stack_size(&interner, target_info), 2);

View file

@ -16,7 +16,7 @@ use roc_mono::{
ir::LambdaSetId,
layout::{
cmp_fields, ext_var_is_empty_tag_union, round_up_to_alignment, Builtin, Discriminant,
InLayout, Layout, LayoutCache, LayoutInterner, TLLayoutInterner, UnionLayout,
InLayout, Layout, LayoutCache, LayoutInterner, LayoutRepr, TLLayoutInterner, UnionLayout,
},
};
use roc_target::{Architecture, OperatingSystem, TargetInfo};
@ -1383,26 +1383,28 @@ fn add_type_help<'a>(
add_tag_union(env, opt_name, tags, var, types, layout, Some(rec_root))
}
Content::Structure(FlatType::Apply(symbol, _)) => match env.layout_cache.get_in(layout) {
Layout::Builtin(builtin) => {
add_builtin_type(env, builtin, var, opt_name, types, layout)
}
_ => {
if symbol.is_builtin() {
todo!(
"Handle Apply for builtin symbol {:?} and layout {:?}",
symbol,
layout
)
} else {
todo!(
"Handle non-builtin Apply for symbol {:?} and layout {:?}",
symbol,
layout
)
Content::Structure(FlatType::Apply(symbol, _)) => {
match env.layout_cache.get_in(layout).repr {
LayoutRepr::Builtin(builtin) => {
add_builtin_type(env, builtin, var, opt_name, types, layout)
}
_ => {
if symbol.is_builtin() {
todo!(
"Handle Apply for builtin symbol {:?} and layout {:?}",
symbol,
layout
)
} else {
todo!(
"Handle non-builtin Apply for symbol {:?} and layout {:?}",
symbol,
layout
)
}
}
}
},
}
Content::Structure(FlatType::Func(args, closure_var, ret_var)) => {
let is_toplevel = false; // or in any case, we cannot assume that we are
@ -1430,11 +1432,11 @@ fn add_type_help<'a>(
}
Content::Alias(name, alias_vars, real_var, _) => {
if name.is_builtin() {
match env.layout_cache.get_in(layout) {
Layout::Builtin(builtin) => {
match env.layout_cache.get_in(layout).repr {
LayoutRepr::Builtin(builtin) => {
add_builtin_type(env, builtin, var, opt_name, types, layout)
}
Layout::Union(union_layout) if *name == Symbol::BOOL_BOOL => {
LayoutRepr::Union(union_layout) if *name == Symbol::BOOL_BOOL => {
if cfg!(debug_assertions) {
match union_layout {
UnionLayout::NonRecursive(tag_layouts) => {
@ -1451,7 +1453,7 @@ fn add_type_help<'a>(
types.add_anonymous(&env.layout_cache.interner, RocType::Bool, layout)
}
Layout::Union(union_layout) if *name == Symbol::RESULT_RESULT => {
LayoutRepr::Union(union_layout) if *name == Symbol::RESULT_RESULT => {
match union_layout {
UnionLayout::NonRecursive(tags) => {
// Result should always have exactly two tags: Ok and Err
@ -1489,12 +1491,12 @@ fn add_type_help<'a>(
}
}
}
Layout::Struct { .. } if *name == Symbol::RESULT_RESULT => {
LayoutRepr::Struct { .. } if *name == Symbol::RESULT_RESULT => {
// can happen if one or both of a and b in `Result.Result a b` are the
// empty tag union `[]`
add_type_help(env, layout, *real_var, opt_name, types)
}
Layout::Struct { .. } if *name == Symbol::DICT_DICT => {
LayoutRepr::Struct { .. } if *name == Symbol::DICT_DICT => {
let type_vars = env.subs.get_subs_slice(alias_vars.type_variables());
let key_var = type_vars[0];
@ -1520,7 +1522,7 @@ fn add_type_help<'a>(
type_id
}
Layout::Struct { .. } if *name == Symbol::SET_SET => {
LayoutRepr::Struct { .. } if *name == Symbol::SET_SET => {
let type_vars = env.subs.get_subs_slice(alias_vars.type_variables());
let key_var = type_vars[0];
@ -1685,11 +1687,11 @@ fn add_builtin_type<'a>(
Alias(Symbol::DICT_DICT, _alias_variables, alias_var, AliasKind::Opaque),
) => {
match (
env.layout_cache.get_in(elem_layout),
env.layout_cache.get_in(elem_layout).repr,
env.subs.get_content_without_compacting(*alias_var),
) {
(
Layout::Struct { field_layouts, .. },
LayoutRepr::Struct { field_layouts, .. },
Content::Structure(FlatType::Apply(Symbol::LIST_LIST, args_subs_slice)),
) => {
let (key_var, val_var) = {
@ -1735,11 +1737,11 @@ fn add_builtin_type<'a>(
Alias(Symbol::SET_SET, _alias_vars, alias_var, AliasKind::Opaque),
) => {
match (
env.layout_cache.get_in(elem_layout),
env.layout_cache.get_in(elem_layout).repr,
env.subs.get_content_without_compacting(*alias_var),
) {
(
Layout::Struct { field_layouts, .. },
LayoutRepr::Struct { field_layouts, .. },
Alias(Symbol::DICT_DICT, alias_args, _alias_var, AliasKind::Opaque),
) => {
let dict_type_vars = env.subs.get_subs_slice(alias_args.type_variables());
@ -1908,7 +1910,7 @@ fn tag_union_type_from_layout<'a>(
) -> RocTagUnion {
let subs = env.subs;
match env.layout_cache.get_in(layout) {
match env.layout_cache.get_in(layout).repr {
_ if union_tags.is_newtype_wrapper(subs)
&& matches!(
subs.get_content_without_compacting(var),
@ -1929,7 +1931,7 @@ fn tag_union_type_from_layout<'a>(
payload,
}
}
Layout::Union(union_layout) => {
LayoutRepr::Union(union_layout) => {
use UnionLayout::*;
match union_layout {
@ -2053,10 +2055,10 @@ fn tag_union_type_from_layout<'a>(
}
}
}
Layout::Builtin(Builtin::Int(int_width)) => {
LayoutRepr::Builtin(Builtin::Int(int_width)) => {
add_int_enumeration(union_tags, subs, &name, int_width)
}
Layout::Struct { field_layouts, .. } => {
LayoutRepr::Struct { field_layouts, .. } => {
let (tag_name, payload) =
single_tag_payload_fields(env, union_tags, subs, layout, field_layouts, types);
@ -2066,13 +2068,13 @@ fn tag_union_type_from_layout<'a>(
payload,
}
}
Layout::Builtin(Builtin::Bool) => {
LayoutRepr::Builtin(Builtin::Bool) => {
// This isn't actually a Bool, but rather a 2-tag union with no payloads
// (so it has the same layout as a Bool, but actually isn't one; if it were
// a real Bool, it would have been handled elsewhere already!)
add_int_enumeration(union_tags, subs, &name, IntWidth::U8)
}
Layout::Builtin(builtin) => {
LayoutRepr::Builtin(builtin) => {
let type_id = add_builtin_type(env, builtin, var, opt_name, types, layout);
let (tag_name, _) = single_tag_payload(union_tags, subs);
@ -2085,7 +2087,7 @@ fn tag_union_type_from_layout<'a>(
},
}
}
Layout::Boxed(elem_layout) => {
LayoutRepr::Boxed(elem_layout) => {
let (tag_name, payload_fields) =
single_tag_payload_fields(env, union_tags, subs, layout, &[elem_layout], types);
@ -2095,7 +2097,7 @@ fn tag_union_type_from_layout<'a>(
payload: payload_fields,
}
}
Layout::LambdaSet(lambda_set) => tag_union_type_from_layout(
LayoutRepr::LambdaSet(lambda_set) => tag_union_type_from_layout(
env,
opt_name,
name,
@ -2104,7 +2106,7 @@ fn tag_union_type_from_layout<'a>(
types,
lambda_set.runtime_representation(),
),
Layout::RecursivePointer(_) => {
LayoutRepr::RecursivePointer(_) => {
// A single-tag union which only wraps itself is erroneous and should have
// been turned into an error earlier in the process.
unreachable!();

View file

@ -11,7 +11,7 @@ use roc_module::symbol::{Interns, ModuleId, Symbol};
use roc_mono::ir::ProcLayout;
use roc_mono::layout::{
self, cmp_fields, union_sorted_tags_pub, Builtin, InLayout, Layout, LayoutCache,
LayoutInterner, TLLayoutInterner, UnionLayout, UnionVariant, WrappedVariant,
LayoutInterner, LayoutRepr, TLLayoutInterner, UnionLayout, UnionVariant, WrappedVariant,
};
use roc_parse::ast::{AssignedField, Collection, Expr, Pattern, StrLiteral};
use roc_region::all::{Loc, Region};
@ -353,13 +353,13 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
};
}
let expr = match env.layout_cache.get_in(layout) {
Layout::Builtin(Builtin::Bool) => {
let expr = match env.layout_cache.get_in(layout).repr {
LayoutRepr::Builtin(Builtin::Bool) => {
app.call_function(main_fn_name, |_mem: &A::Memory, num: bool| {
bool_to_ast(env, num, env.subs.get_content_without_compacting(raw_var))
})
}
Layout::Builtin(Builtin::Int(int_width)) => {
LayoutRepr::Builtin(Builtin::Int(int_width)) => {
use IntWidth::*;
match int_width {
@ -386,7 +386,7 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
I128 => num_helper!(i128),
}
}
Layout::Builtin(Builtin::Float(float_width)) => {
LayoutRepr::Builtin(Builtin::Float(float_width)) => {
use FloatWidth::*;
match float_width {
@ -394,8 +394,8 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
F64 => num_helper!(f64),
}
}
Layout::Builtin(Builtin::Decimal) => num_helper!(RocDec),
Layout::Builtin(Builtin::Str) => {
LayoutRepr::Builtin(Builtin::Decimal) => num_helper!(RocDec),
LayoutRepr::Builtin(Builtin::Str) => {
let body = |mem: &A::Memory, addr| {
let string = mem.deref_str(addr);
let arena_str = env.arena.alloc_str(string);
@ -404,7 +404,7 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
app.call_function_returns_roc_str(env.target_info, main_fn_name, body)
}
Layout::Builtin(Builtin::List(elem_layout)) => app.call_function_returns_roc_list(
LayoutRepr::Builtin(Builtin::List(elem_layout)) => app.call_function_returns_roc_list(
main_fn_name,
|mem: &A::Memory, (addr, len, _cap)| {
list_to_ast(
@ -417,7 +417,7 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
)
},
),
Layout::Struct { field_layouts, .. } => {
LayoutRepr::Struct { field_layouts, .. } => {
let fields = [Layout::U64, layout];
let layout = env
.layout_cache
@ -466,7 +466,7 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
struct_addr_to_ast,
)
}
Layout::Union(UnionLayout::NonRecursive(_)) => {
LayoutRepr::Union(UnionLayout::NonRecursive(_)) => {
let size = env.layout_cache.interner.stack_size(layout);
app.call_function_dynamic_size(
@ -484,10 +484,10 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
},
)
}
Layout::Union(UnionLayout::Recursive(_))
| Layout::Union(UnionLayout::NonNullableUnwrapped(_))
| Layout::Union(UnionLayout::NullableUnwrapped { .. })
| Layout::Union(UnionLayout::NullableWrapped { .. }) => {
LayoutRepr::Union(UnionLayout::Recursive(_))
| LayoutRepr::Union(UnionLayout::NonNullableUnwrapped(_))
| LayoutRepr::Union(UnionLayout::NullableUnwrapped { .. })
| LayoutRepr::Union(UnionLayout::NullableWrapped { .. }) => {
let size = env.layout_cache.interner.stack_size(layout);
app.call_function_dynamic_size(
@ -505,11 +505,11 @@ fn jit_to_ast_help<'a, A: ReplApp<'a>>(
},
)
}
Layout::RecursivePointer(_) => {
LayoutRepr::RecursivePointer(_) => {
unreachable!("RecursivePointers can only be inside structures")
}
Layout::LambdaSet(_) => OPAQUE_FUNCTION,
Layout::Boxed(_) => {
LayoutRepr::LambdaSet(_) => OPAQUE_FUNCTION,
LayoutRepr::Boxed(_) => {
let size = env.layout_cache.interner.stack_size(layout);
app.call_function_dynamic_size(main_fn_name, size as usize, |mem: &A::Memory, addr| {
@ -559,11 +559,11 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
let (newtype_containers, _alias_content, raw_var) = unroll_newtypes_and_aliases(env, var);
let raw_content = env.subs.get_content_without_compacting(raw_var);
let expr = match (raw_content, env.layout_cache.get_in(layout)) {
(Content::Structure(FlatType::Func(_, _, _)), _) | (_, Layout::LambdaSet(_)) => {
let expr = match (raw_content, env.layout_cache.get_in(layout).repr) {
(Content::Structure(FlatType::Func(_, _, _)), _) | (_, LayoutRepr::LambdaSet(_)) => {
OPAQUE_FUNCTION
}
(_, Layout::Builtin(Builtin::Bool)) => {
(_, LayoutRepr::Builtin(Builtin::Bool)) => {
// TODO: bits are not as expected here.
// num is always false at the moment.
let num: u8 = mem.deref_u8(addr);
@ -572,7 +572,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
bool_to_ast(env, num != 0, raw_content)
}
(_, Layout::Builtin(Builtin::Int(int_width))) => {
(_, LayoutRepr::Builtin(Builtin::Int(int_width))) => {
use IntWidth::*;
match int_width {
@ -594,7 +594,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
I128 => helper!(deref_i128, i128),
}
}
(_, Layout::Builtin(Builtin::Float(float_width))) => {
(_, LayoutRepr::Builtin(Builtin::Float(float_width))) => {
use FloatWidth::*;
match float_width {
@ -602,22 +602,22 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
F64 => helper!(deref_f64, f64),
}
}
(_, Layout::Builtin(Builtin::Decimal)) => {
(_, LayoutRepr::Builtin(Builtin::Decimal)) => {
helper!(deref_dec, RocDec)
}
(_, Layout::Builtin(Builtin::List(elem_layout))) => {
(_, LayoutRepr::Builtin(Builtin::List(elem_layout))) => {
let elem_addr = mem.deref_usize(addr);
let len = mem.deref_usize(addr + env.target_info.ptr_width() as usize);
let _cap = mem.deref_usize(addr + 2 * env.target_info.ptr_width() as usize);
list_to_ast(env, mem, elem_addr, len, elem_layout, raw_content)
}
(_, Layout::Builtin(Builtin::Str)) => {
(_, LayoutRepr::Builtin(Builtin::Str)) => {
let string = mem.deref_str(addr);
let arena_str = env.arena.alloc_str(string);
Expr::Str(StrLiteral::PlainLine(arena_str))
}
(_, Layout::Struct { field_layouts, .. }) => match raw_content {
(_, LayoutRepr::Struct { field_layouts, .. }) => match raw_content {
Content::Structure(FlatType::Record(fields, _)) => {
struct_to_ast(env, mem, addr, *fields)
}
@ -644,7 +644,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
);
}
},
(_, Layout::RecursivePointer(_)) => match (raw_content, when_recursive) {
(_, LayoutRepr::RecursivePointer(_)) => match (raw_content, when_recursive) {
(
Content::RecursionVar {
structure,
@ -667,13 +667,13 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
let union_layout = env.layout_cache
.from_var(env.arena, *structure, env.subs)
.expect("no layout for structure");
debug_assert!(matches!(env.layout_cache.get_in(union_layout), Layout::Union(..)));
debug_assert!(matches!(env.layout_cache.get_in(union_layout).repr, LayoutRepr::Union(..)));
let when_recursive = WhenRecursive::Loop(union_layout);
addr_to_ast(env, mem, addr, union_layout, when_recursive, *structure)
}
other => unreachable!("Something had a RecursivePointer layout, but instead of being a RecursionVar and having a known recursive layout, I found {:?}", other),
},
(_, Layout::Union(UnionLayout::NonRecursive(union_layouts))) => {
(_, LayoutRepr::Union(UnionLayout::NonRecursive(union_layouts))) => {
let union_layout = UnionLayout::NonRecursive(union_layouts);
let tags = match raw_content {
@ -708,7 +708,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
WhenRecursive::Unreachable,
)
}
(_, Layout::Union(union_layout @ UnionLayout::Recursive(union_layouts))) => {
(_, LayoutRepr::Union(union_layout @ UnionLayout::Recursive(union_layouts))) => {
let (rec_var, tags) = match raw_content {
Content::Structure(FlatType::RecursiveTagUnion(rec_var, tags, _)) => {
(rec_var, tags)
@ -747,7 +747,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
when_recursive,
)
}
(_, Layout::Union(UnionLayout::NonNullableUnwrapped(_))) => {
(_, LayoutRepr::Union(UnionLayout::NonNullableUnwrapped(_))) => {
let (rec_var, tags) = match unroll_recursion_var(env, raw_content) {
Content::Structure(FlatType::RecursiveTagUnion(rec_var, tags, _)) => {
(rec_var, tags)
@ -778,7 +778,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
when_recursive,
)
}
(_, Layout::Union(UnionLayout::NullableUnwrapped { .. })) => {
(_, LayoutRepr::Union(UnionLayout::NullableUnwrapped { .. })) => {
let (rec_var, tags) = match unroll_recursion_var(env, raw_content) {
Content::Structure(FlatType::RecursiveTagUnion(rec_var, tags, _)) => {
(rec_var, tags)
@ -818,7 +818,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
)
}
}
(_, Layout::Union(union_layout @ UnionLayout::NullableWrapped { .. })) => {
(_, LayoutRepr::Union(union_layout @ UnionLayout::NullableWrapped { .. })) => {
let (rec_var, tags) = match unroll_recursion_var(env, raw_content) {
Content::Structure(FlatType::RecursiveTagUnion(rec_var, tags, _)) => {
(rec_var, tags)
@ -863,7 +863,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
}
(
Content::Structure(FlatType::Apply(Symbol::BOX_BOX_TYPE, args)),
Layout::Boxed(inner_layout),
LayoutRepr::Boxed(inner_layout),
) => {
debug_assert_eq!(args.len(), 1);
@ -889,7 +889,7 @@ fn addr_to_ast<'a, M: ReplAppMemory>(
Expr::Apply(box_box, box_box_args, CalledVia::Space)
}
(_, Layout::Boxed(_)) => {
(_, LayoutRepr::Boxed(_)) => {
unreachable!("Box layouts can only be behind a `Box.Box` application")
}
};