mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 12:18:19 +00:00
Wrap layouts in a LayoutRepr
constructor
Part 1 of support semantic layout representations.
This commit is contained in:
parent
c2d2bd4bb9
commit
c3eeb5e2cc
32 changed files with 1254 additions and 1021 deletions
|
@ -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);
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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!(),
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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!();
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue