mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 00:01:16 +00:00
Merge branch 'trunk' of github.com:rtfeldman/roc into repl_from_memory_trait
This commit is contained in:
commit
382ae948e1
67 changed files with 950 additions and 680 deletions
|
@ -590,7 +590,9 @@ fn eq_list<'a>(
|
|||
|
||||
// let size = literal int
|
||||
let size = root.create_symbol(ident_ids, "size");
|
||||
let size_expr = Expr::Literal(Literal::Int(elem_layout.stack_size(root.ptr_size) as i128));
|
||||
let size_expr = Expr::Literal(Literal::Int(
|
||||
elem_layout.stack_size(root.target_info) as i128
|
||||
));
|
||||
let size_stmt = |next| Stmt::Let(size, size_expr, layout_isize, next);
|
||||
|
||||
// let list_size = len_1 * size
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use bumpalo::collections::vec::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_builtins::bitcode::IntWidth;
|
||||
use roc_module::ident::Ident;
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
||||
use roc_target::TargetInfo;
|
||||
|
||||
use crate::ir::{
|
||||
Call, CallSpecId, CallType, Expr, HostExposedLayouts, JoinPointId, ModifyRc, Proc, ProcLayout,
|
||||
|
@ -74,19 +74,19 @@ pub struct Context<'a> {
|
|||
pub struct CodeGenHelp<'a> {
|
||||
arena: &'a Bump,
|
||||
home: ModuleId,
|
||||
ptr_size: u32,
|
||||
target_info: TargetInfo,
|
||||
layout_isize: Layout<'a>,
|
||||
specializations: Vec<'a, Specialization<'a>>,
|
||||
debug_recursion_depth: usize,
|
||||
}
|
||||
|
||||
impl<'a> CodeGenHelp<'a> {
|
||||
pub fn new(arena: &'a Bump, intwidth_isize: IntWidth, home: ModuleId) -> Self {
|
||||
pub fn new(arena: &'a Bump, target_info: TargetInfo, home: ModuleId) -> Self {
|
||||
CodeGenHelp {
|
||||
arena,
|
||||
home,
|
||||
ptr_size: intwidth_isize.stack_size(),
|
||||
layout_isize: Layout::Builtin(Builtin::Int(intwidth_isize)),
|
||||
target_info,
|
||||
layout_isize: Layout::usize(target_info),
|
||||
specializations: Vec::with_capacity_in(16, arena),
|
||||
debug_recursion_depth: 0,
|
||||
}
|
||||
|
|
|
@ -207,7 +207,7 @@ pub fn rc_ptr_from_data_ptr<'a>(
|
|||
|
||||
// Mask for lower bits (for tag union id)
|
||||
let mask_sym = root.create_symbol(ident_ids, "mask");
|
||||
let mask_expr = Expr::Literal(Literal::Int(-(root.ptr_size as i128)));
|
||||
let mask_expr = Expr::Literal(Literal::Int(-(root.target_info.ptr_width() as i128)));
|
||||
let mask_stmt = |next| Stmt::Let(mask_sym, mask_expr, root.layout_isize, next);
|
||||
|
||||
let masked_sym = root.create_symbol(ident_ids, "masked");
|
||||
|
@ -222,7 +222,7 @@ pub fn rc_ptr_from_data_ptr<'a>(
|
|||
|
||||
// Pointer size constant
|
||||
let ptr_size_sym = root.create_symbol(ident_ids, "ptr_size");
|
||||
let ptr_size_expr = Expr::Literal(Literal::Int(root.ptr_size as i128));
|
||||
let ptr_size_expr = Expr::Literal(Literal::Int(root.target_info.ptr_width() as i128));
|
||||
let ptr_size_stmt = |next| Stmt::Let(ptr_size_sym, ptr_size_expr, root.layout_isize, next);
|
||||
|
||||
// Refcount address
|
||||
|
@ -382,7 +382,7 @@ fn refcount_str<'a>(
|
|||
|
||||
// A pointer to the refcount value itself
|
||||
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
|
||||
let alignment = root.ptr_size;
|
||||
let alignment = root.target_info.ptr_width() as u32;
|
||||
|
||||
let ret_unit_stmt = rc_return_stmt(root, ident_ids, ctx);
|
||||
let mod_rc_stmt = modify_refcount(
|
||||
|
@ -487,7 +487,7 @@ fn refcount_list<'a>(
|
|||
//
|
||||
|
||||
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
|
||||
let alignment = layout.alignment_bytes(root.ptr_size);
|
||||
let alignment = layout.alignment_bytes(root.target_info);
|
||||
|
||||
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
|
||||
let modify_list = modify_refcount(
|
||||
|
@ -584,7 +584,9 @@ fn refcount_list_elems<'a>(
|
|||
|
||||
// let size = literal int
|
||||
let elem_size = root.create_symbol(ident_ids, "elem_size");
|
||||
let elem_size_expr = Expr::Literal(Literal::Int(elem_layout.stack_size(root.ptr_size) as i128));
|
||||
let elem_size_expr = Expr::Literal(Literal::Int(
|
||||
elem_layout.stack_size(root.target_info) as i128
|
||||
));
|
||||
let elem_size_stmt = |next| Stmt::Let(elem_size, elem_size_expr, layout_isize, next);
|
||||
|
||||
// let list_size = len * size
|
||||
|
@ -972,7 +974,7 @@ fn refcount_union_rec<'a>(
|
|||
let rc_structure_stmt = {
|
||||
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
|
||||
|
||||
let alignment = Layout::Union(union_layout).alignment_bytes(root.ptr_size);
|
||||
let alignment = Layout::Union(union_layout).alignment_bytes(root.target_info);
|
||||
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
|
||||
let modify_structure_stmt = modify_refcount(
|
||||
root,
|
||||
|
@ -988,7 +990,7 @@ fn refcount_union_rec<'a>(
|
|||
ident_ids,
|
||||
structure,
|
||||
rc_ptr,
|
||||
union_layout.stores_tag_id_in_pointer(root.ptr_size),
|
||||
union_layout.stores_tag_id_in_pointer(root.target_info),
|
||||
root.arena.alloc(modify_structure_stmt),
|
||||
)
|
||||
};
|
||||
|
@ -1080,7 +1082,7 @@ fn refcount_union_tailrec<'a>(
|
|||
)
|
||||
};
|
||||
|
||||
let alignment = layout.alignment_bytes(root.ptr_size);
|
||||
let alignment = layout.alignment_bytes(root.target_info);
|
||||
let modify_structure_stmt = modify_refcount(
|
||||
root,
|
||||
ident_ids,
|
||||
|
@ -1095,7 +1097,7 @@ fn refcount_union_tailrec<'a>(
|
|||
ident_ids,
|
||||
current,
|
||||
rc_ptr,
|
||||
union_layout.stores_tag_id_in_pointer(root.ptr_size),
|
||||
union_layout.stores_tag_id_in_pointer(root.target_info),
|
||||
root.arena.alloc(modify_structure_stmt),
|
||||
)
|
||||
};
|
||||
|
|
|
@ -16,6 +16,7 @@ use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
|||
use roc_problem::can::RuntimeError;
|
||||
use roc_region::all::{Loc, Region};
|
||||
use roc_std::RocDec;
|
||||
use roc_target::TargetInfo;
|
||||
use roc_types::subs::{Content, FlatType, StorageSubs, Subs, Variable, VariableSubsSlice};
|
||||
use std::collections::HashMap;
|
||||
use ven_pretty::{BoxAllocator, DocAllocator, DocBuilder};
|
||||
|
@ -1071,7 +1072,7 @@ pub struct Env<'a, 'i> {
|
|||
pub problems: &'i mut std::vec::Vec<MonoProblem>,
|
||||
pub home: ModuleId,
|
||||
pub ident_ids: &'i mut IdentIds,
|
||||
pub ptr_bytes: u32,
|
||||
pub target_info: TargetInfo,
|
||||
pub update_mode_ids: &'i mut UpdateModeIds,
|
||||
pub call_specialization_counter: u32,
|
||||
}
|
||||
|
@ -2471,7 +2472,7 @@ fn specialize_external<'a>(
|
|||
env.arena,
|
||||
);
|
||||
|
||||
let ptr_bytes = env.ptr_bytes;
|
||||
let ptr_bytes = env.target_info;
|
||||
|
||||
combined.sort_by(|(_, layout1), (_, layout2)| {
|
||||
let size1 = layout1.alignment_bytes(ptr_bytes);
|
||||
|
@ -2504,7 +2505,7 @@ fn specialize_external<'a>(
|
|||
env.arena,
|
||||
);
|
||||
|
||||
let ptr_bytes = env.ptr_bytes;
|
||||
let ptr_bytes = env.target_info;
|
||||
|
||||
combined.sort_by(|(_, layout1), (_, layout2)| {
|
||||
let size1 = layout1.alignment_bytes(ptr_bytes);
|
||||
|
@ -3009,14 +3010,14 @@ fn try_make_literal<'a>(
|
|||
|
||||
match can_expr {
|
||||
Int(_, precision, _, int) => {
|
||||
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, *precision, false) {
|
||||
match num_argument_to_int_or_float(env.subs, env.target_info, *precision, false) {
|
||||
IntOrFloat::Int(_) => Some(Literal::Int(*int)),
|
||||
_ => unreachable!("unexpected float precision for integer"),
|
||||
}
|
||||
}
|
||||
|
||||
Float(_, precision, float_str, float) => {
|
||||
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, *precision, true) {
|
||||
match num_argument_to_int_or_float(env.subs, env.target_info, *precision, true) {
|
||||
IntOrFloat::Float(_) => Some(Literal::Float(*float)),
|
||||
IntOrFloat::DecimalFloatType => {
|
||||
let dec = match RocDec::from_str(float_str) {
|
||||
|
@ -3037,7 +3038,7 @@ fn try_make_literal<'a>(
|
|||
// Str(string) => Some(Literal::Str(env.arena.alloc(string))),
|
||||
Num(var, num_str, num) => {
|
||||
// first figure out what kind of number this is
|
||||
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, *var, false) {
|
||||
match num_argument_to_int_or_float(env.subs, env.target_info, *var, false) {
|
||||
IntOrFloat::Int(_) => Some(Literal::Int((*num).into())),
|
||||
IntOrFloat::Float(_) => Some(Literal::Float(*num as f64)),
|
||||
IntOrFloat::DecimalFloatType => {
|
||||
|
@ -3072,7 +3073,7 @@ pub fn with_hole<'a>(
|
|||
|
||||
match can_expr {
|
||||
Int(_, precision, _, int) => {
|
||||
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, precision, false) {
|
||||
match num_argument_to_int_or_float(env.subs, env.target_info, precision, false) {
|
||||
IntOrFloat::Int(precision) => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Int(int)),
|
||||
|
@ -3084,7 +3085,7 @@ pub fn with_hole<'a>(
|
|||
}
|
||||
|
||||
Float(_, precision, float_str, float) => {
|
||||
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, precision, true) {
|
||||
match num_argument_to_int_or_float(env.subs, env.target_info, precision, true) {
|
||||
IntOrFloat::Float(precision) => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Float(float)),
|
||||
|
@ -3116,7 +3117,7 @@ pub fn with_hole<'a>(
|
|||
|
||||
Num(var, num_str, num) => {
|
||||
// first figure out what kind of number this is
|
||||
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, var, false) {
|
||||
match num_argument_to_int_or_float(env.subs, env.target_info, var, false) {
|
||||
IntOrFloat::Int(precision) => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Int(num.into())),
|
||||
|
@ -3393,7 +3394,7 @@ pub fn with_hole<'a>(
|
|||
env.arena,
|
||||
record_var,
|
||||
env.subs,
|
||||
env.ptr_bytes,
|
||||
env.target_info,
|
||||
) {
|
||||
Ok(fields) => fields,
|
||||
Err(_) => return Stmt::RuntimeError("Can't create record with improper layout"),
|
||||
|
@ -3754,7 +3755,7 @@ pub fn with_hole<'a>(
|
|||
env.arena,
|
||||
record_var,
|
||||
env.subs,
|
||||
env.ptr_bytes,
|
||||
env.target_info,
|
||||
) {
|
||||
Ok(fields) => fields,
|
||||
Err(_) => return Stmt::RuntimeError("Can't access record with improper layout"),
|
||||
|
@ -3911,7 +3912,7 @@ pub fn with_hole<'a>(
|
|||
env.arena,
|
||||
record_var,
|
||||
env.subs,
|
||||
env.ptr_bytes,
|
||||
env.target_info,
|
||||
) {
|
||||
Ok(fields) => fields,
|
||||
Err(_) => return Stmt::RuntimeError("Can't update record with improper layout"),
|
||||
|
@ -4586,7 +4587,7 @@ fn construct_closure_data<'a>(
|
|||
env.arena,
|
||||
);
|
||||
|
||||
let ptr_bytes = env.ptr_bytes;
|
||||
let ptr_bytes = env.target_info;
|
||||
|
||||
combined.sort_by(|(_, layout1), (_, layout2)| {
|
||||
let size1 = layout1.alignment_bytes(ptr_bytes);
|
||||
|
@ -4617,7 +4618,7 @@ fn construct_closure_data<'a>(
|
|||
env.arena,
|
||||
);
|
||||
|
||||
let ptr_bytes = env.ptr_bytes;
|
||||
let ptr_bytes = env.target_info;
|
||||
|
||||
combined.sort_by(|(_, layout1), (_, layout2)| {
|
||||
let size1 = layout1.alignment_bytes(ptr_bytes);
|
||||
|
@ -4692,7 +4693,7 @@ fn convert_tag_union<'a>(
|
|||
) -> Stmt<'a> {
|
||||
use crate::layout::UnionVariant::*;
|
||||
let res_variant =
|
||||
crate::layout::union_sorted_tags(env.arena, variant_var, env.subs, env.ptr_bytes);
|
||||
crate::layout::union_sorted_tags(env.arena, variant_var, env.subs, env.target_info);
|
||||
let variant = match res_variant {
|
||||
Ok(cached) => cached,
|
||||
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
|
||||
|
@ -5035,7 +5036,7 @@ fn sorted_field_symbols<'a>(
|
|||
}
|
||||
};
|
||||
|
||||
let alignment = layout.alignment_bytes(env.ptr_bytes);
|
||||
let alignment = layout.alignment_bytes(env.target_info);
|
||||
|
||||
let symbol = possible_reuse_symbol(env, procs, &arg.value);
|
||||
field_symbols_temp.push((alignment, symbol, ((var, arg), &*env.arena.alloc(symbol))));
|
||||
|
@ -5120,7 +5121,7 @@ fn register_capturing_closure<'a>(
|
|||
|
||||
let captured_symbols = match *env.subs.get_content_without_compacting(function_type) {
|
||||
Content::Structure(FlatType::Func(_, closure_var, _)) => {
|
||||
match LambdaSet::from_var(env.arena, env.subs, closure_var, env.ptr_bytes) {
|
||||
match LambdaSet::from_var(env.arena, env.subs, closure_var, env.target_info) {
|
||||
Ok(lambda_set) => {
|
||||
if let Layout::Struct(&[]) = lambda_set.runtime_representation() {
|
||||
CapturedSymbols::None
|
||||
|
@ -7621,7 +7622,7 @@ fn from_can_pattern_help<'a>(
|
|||
Underscore => Ok(Pattern::Underscore),
|
||||
Identifier(symbol) => Ok(Pattern::Identifier(*symbol)),
|
||||
IntLiteral(var, _, int) => {
|
||||
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, *var, false) {
|
||||
match num_argument_to_int_or_float(env.subs, env.target_info, *var, false) {
|
||||
IntOrFloat::Int(precision) => Ok(Pattern::IntLiteral(*int as i128, precision)),
|
||||
other => {
|
||||
panic!(
|
||||
|
@ -7633,7 +7634,7 @@ fn from_can_pattern_help<'a>(
|
|||
}
|
||||
FloatLiteral(var, float_str, float) => {
|
||||
// TODO: Can I reuse num_argument_to_int_or_float here if I pass in true?
|
||||
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, *var, true) {
|
||||
match num_argument_to_int_or_float(env.subs, env.target_info, *var, true) {
|
||||
IntOrFloat::Int(_) => {
|
||||
panic!("Invalid precision for float pattern {:?}", var)
|
||||
}
|
||||
|
@ -7663,7 +7664,7 @@ fn from_can_pattern_help<'a>(
|
|||
Err(RuntimeError::UnsupportedPattern(*region))
|
||||
}
|
||||
NumLiteral(var, num_str, num) => {
|
||||
match num_argument_to_int_or_float(env.subs, env.ptr_bytes, *var, false) {
|
||||
match num_argument_to_int_or_float(env.subs, env.target_info, *var, false) {
|
||||
IntOrFloat::Int(precision) => Ok(Pattern::IntLiteral(*num as i128, precision)),
|
||||
IntOrFloat::Float(precision) => Ok(Pattern::FloatLiteral(*num as u64, precision)),
|
||||
IntOrFloat::DecimalFloatType => {
|
||||
|
@ -7686,7 +7687,7 @@ fn from_can_pattern_help<'a>(
|
|||
use crate::layout::UnionVariant::*;
|
||||
|
||||
let res_variant =
|
||||
crate::layout::union_sorted_tags(env.arena, *whole_var, env.subs, env.ptr_bytes)
|
||||
crate::layout::union_sorted_tags(env.arena, *whole_var, env.subs, env.target_info)
|
||||
.map_err(Into::into);
|
||||
|
||||
let variant = match res_variant {
|
||||
|
@ -7768,12 +7769,12 @@ fn from_can_pattern_help<'a>(
|
|||
arguments.sort_by(|arg1, arg2| {
|
||||
let size1 = layout_cache
|
||||
.from_var(env.arena, arg1.0, env.subs)
|
||||
.map(|x| x.alignment_bytes(env.ptr_bytes))
|
||||
.map(|x| x.alignment_bytes(env.target_info))
|
||||
.unwrap_or(0);
|
||||
|
||||
let size2 = layout_cache
|
||||
.from_var(env.arena, arg2.0, env.subs)
|
||||
.map(|x| x.alignment_bytes(env.ptr_bytes))
|
||||
.map(|x| x.alignment_bytes(env.target_info))
|
||||
.unwrap_or(0);
|
||||
|
||||
size2.cmp(&size1)
|
||||
|
@ -7806,8 +7807,8 @@ fn from_can_pattern_help<'a>(
|
|||
let layout2 =
|
||||
layout_cache.from_var(env.arena, arg2.0, env.subs).unwrap();
|
||||
|
||||
let size1 = layout1.alignment_bytes(env.ptr_bytes);
|
||||
let size2 = layout2.alignment_bytes(env.ptr_bytes);
|
||||
let size1 = layout1.alignment_bytes(env.target_info);
|
||||
let size2 = layout2.alignment_bytes(env.target_info);
|
||||
|
||||
size2.cmp(&size1)
|
||||
});
|
||||
|
@ -8107,7 +8108,7 @@ fn from_can_pattern_help<'a>(
|
|||
} => {
|
||||
// sorted fields based on the type
|
||||
let sorted_fields =
|
||||
crate::layout::sort_record_fields(env.arena, *whole_var, env.subs, env.ptr_bytes)
|
||||
crate::layout::sort_record_fields(env.arena, *whole_var, env.subs, env.target_info)
|
||||
.map_err(RuntimeError::from)?;
|
||||
|
||||
// sorted fields based on the destruct
|
||||
|
@ -8259,7 +8260,7 @@ pub enum IntOrFloat {
|
|||
/// Given the `a` in `Num a`, determines whether it's an int or a float
|
||||
pub fn num_argument_to_int_or_float(
|
||||
subs: &Subs,
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
var: Variable,
|
||||
known_to_be_float: bool,
|
||||
) -> IntOrFloat {
|
||||
|
@ -8274,7 +8275,7 @@ pub fn num_argument_to_int_or_float(
|
|||
|
||||
// Recurse on the second argument
|
||||
let var = subs[args.variables().into_iter().next().unwrap()];
|
||||
num_argument_to_int_or_float(subs, ptr_bytes, var, false)
|
||||
num_argument_to_int_or_float(subs, target_info, var, false)
|
||||
}
|
||||
|
||||
other @ Content::Alias(symbol, args, _) => {
|
||||
|
@ -8292,16 +8293,15 @@ pub fn num_argument_to_int_or_float(
|
|||
|
||||
// Recurse on the second argument
|
||||
let var = subs[args.variables().into_iter().next().unwrap()];
|
||||
num_argument_to_int_or_float(subs, ptr_bytes, var, true)
|
||||
num_argument_to_int_or_float(subs, target_info, var, true)
|
||||
}
|
||||
|
||||
Symbol::NUM_DECIMAL | Symbol::NUM_AT_DECIMAL => IntOrFloat::DecimalFloatType,
|
||||
|
||||
Symbol::NUM_NAT | Symbol::NUM_NATURAL | Symbol::NUM_AT_NATURAL => {
|
||||
let int_width = match ptr_bytes {
|
||||
4 => IntWidth::U32,
|
||||
8 => IntWidth::U64,
|
||||
_ => panic!("unsupported word size"),
|
||||
let int_width = match target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes4 => IntWidth::U32,
|
||||
roc_target::PtrWidth::Bytes8 => IntWidth::U64,
|
||||
};
|
||||
|
||||
IntOrFloat::Int(int_width)
|
||||
|
|
|
@ -6,6 +6,7 @@ use roc_collections::all::{default_hasher, MutMap};
|
|||
use roc_module::ident::{Lowercase, TagName};
|
||||
use roc_module::symbol::{Interns, Symbol};
|
||||
use roc_problem::can::RuntimeError;
|
||||
use roc_target::{PtrWidth, TargetInfo};
|
||||
use roc_types::subs::{
|
||||
Content, FlatType, RecordFields, Subs, UnionTags, UnsortedUnionTags, Variable,
|
||||
};
|
||||
|
@ -123,7 +124,7 @@ impl<'a> RawFunctionLayout<'a> {
|
|||
// Nat
|
||||
Alias(Symbol::NUM_NAT, args, _) => {
|
||||
debug_assert!(args.is_empty());
|
||||
Ok(Self::ZeroArgumentThunk(Layout::usize(env.ptr_bytes)))
|
||||
Ok(Self::ZeroArgumentThunk(Layout::usize(env.target_info)))
|
||||
}
|
||||
|
||||
Alias(symbol, _, _) if symbol.is_builtin() => Ok(Self::ZeroArgumentThunk(
|
||||
|
@ -158,7 +159,7 @@ impl<'a> RawFunctionLayout<'a> {
|
|||
let ret = arena.alloc(ret);
|
||||
|
||||
let lambda_set =
|
||||
LambdaSet::from_var(env.arena, env.subs, closure_var, env.ptr_bytes)?;
|
||||
LambdaSet::from_var(env.arena, env.subs, closure_var, env.target_info)?;
|
||||
|
||||
Ok(Self::Function(fn_args, lambda_set, ret))
|
||||
}
|
||||
|
@ -360,37 +361,36 @@ impl<'a> UnionLayout<'a> {
|
|||
Layout::Builtin(self.tag_id_builtin())
|
||||
}
|
||||
|
||||
fn stores_tag_id_in_pointer_bits(tags: &[&[Layout<'a>]], ptr_bytes: u32) -> bool {
|
||||
tags.len() < ptr_bytes as usize
|
||||
fn stores_tag_id_in_pointer_bits(tags: &[&[Layout<'a>]], target_info: TargetInfo) -> bool {
|
||||
tags.len() < target_info.ptr_width() as usize
|
||||
}
|
||||
|
||||
pub fn tag_id_pointer_bits_and_mask(ptr_bytes: u32) -> (usize, usize) {
|
||||
match ptr_bytes {
|
||||
8 => (3, 0b0000_0111),
|
||||
4 => (2, 0b0000_0011),
|
||||
_ => unreachable!(),
|
||||
pub fn tag_id_pointer_bits_and_mask(target_info: TargetInfo) -> (usize, usize) {
|
||||
match target_info.ptr_width() {
|
||||
PtrWidth::Bytes8 => (3, 0b0000_0111),
|
||||
PtrWidth::Bytes4 => (2, 0b0000_0011),
|
||||
}
|
||||
}
|
||||
|
||||
// i.e. it is not implicit and not stored in the pointer bits
|
||||
pub fn stores_tag_id_as_data(&self, ptr_bytes: u32) -> bool {
|
||||
pub fn stores_tag_id_as_data(&self, target_info: TargetInfo) -> bool {
|
||||
match self {
|
||||
UnionLayout::NonRecursive(_) => true,
|
||||
UnionLayout::Recursive(tags)
|
||||
| UnionLayout::NullableWrapped {
|
||||
other_tags: tags, ..
|
||||
} => !Self::stores_tag_id_in_pointer_bits(tags, ptr_bytes),
|
||||
} => !Self::stores_tag_id_in_pointer_bits(tags, target_info),
|
||||
UnionLayout::NonNullableUnwrapped(_) | UnionLayout::NullableUnwrapped { .. } => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stores_tag_id_in_pointer(&self, ptr_bytes: u32) -> bool {
|
||||
pub fn stores_tag_id_in_pointer(&self, target_info: TargetInfo) -> bool {
|
||||
match self {
|
||||
UnionLayout::NonRecursive(_) => false,
|
||||
UnionLayout::Recursive(tags)
|
||||
| UnionLayout::NullableWrapped {
|
||||
other_tags: tags, ..
|
||||
} => Self::stores_tag_id_in_pointer_bits(tags, ptr_bytes),
|
||||
} => Self::stores_tag_id_in_pointer_bits(tags, target_info),
|
||||
UnionLayout::NonNullableUnwrapped(_) | UnionLayout::NullableUnwrapped { .. } => false,
|
||||
}
|
||||
}
|
||||
|
@ -414,76 +414,73 @@ impl<'a> UnionLayout<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn tags_alignment_bytes(tags: &[&[Layout]], pointer_size: u32) -> u32 {
|
||||
fn tags_alignment_bytes(tags: &[&[Layout]], target_info: TargetInfo) -> u32 {
|
||||
tags.iter()
|
||||
.map(|fields| Layout::Struct(fields).alignment_bytes(pointer_size))
|
||||
.map(|fields| Layout::Struct(fields).alignment_bytes(target_info))
|
||||
.max()
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
pub fn allocation_alignment_bytes(&self, pointer_size: u32) -> u32 {
|
||||
pub fn allocation_alignment_bytes(&self, target_info: TargetInfo) -> u32 {
|
||||
let allocation = match self {
|
||||
UnionLayout::NonRecursive(_) => unreachable!("not heap-allocated"),
|
||||
UnionLayout::Recursive(tags) => Self::tags_alignment_bytes(tags, pointer_size),
|
||||
UnionLayout::Recursive(tags) => Self::tags_alignment_bytes(tags, target_info),
|
||||
UnionLayout::NonNullableUnwrapped(fields) => {
|
||||
Layout::Struct(fields).alignment_bytes(pointer_size)
|
||||
Layout::Struct(fields).alignment_bytes(target_info)
|
||||
}
|
||||
UnionLayout::NullableWrapped { other_tags, .. } => {
|
||||
Self::tags_alignment_bytes(other_tags, pointer_size)
|
||||
Self::tags_alignment_bytes(other_tags, target_info)
|
||||
}
|
||||
UnionLayout::NullableUnwrapped { other_fields, .. } => {
|
||||
Layout::Struct(other_fields).alignment_bytes(pointer_size)
|
||||
Layout::Struct(other_fields).alignment_bytes(target_info)
|
||||
}
|
||||
};
|
||||
|
||||
// because we store a refcount, the alignment must be at least the size of a pointer
|
||||
allocation.max(pointer_size)
|
||||
allocation.max(target_info.ptr_width() as u32)
|
||||
}
|
||||
|
||||
/// Size of the data in memory, whether it's stack or heap (for non-null tag ids)
|
||||
pub fn data_size_and_alignment(&self, pointer_size: u32) -> (u32, u32) {
|
||||
let id_data_layout = if self.stores_tag_id_as_data(pointer_size) {
|
||||
pub fn data_size_and_alignment(&self, target_info: TargetInfo) -> (u32, u32) {
|
||||
let id_data_layout = if self.stores_tag_id_as_data(target_info) {
|
||||
Some(self.tag_id_layout())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
self.data_size_and_alignment_help_match(id_data_layout, pointer_size)
|
||||
self.data_size_and_alignment_help_match(id_data_layout, target_info)
|
||||
}
|
||||
|
||||
/// Size of the data before the tag_id, if it exists.
|
||||
/// Returns None if the tag_id is not stored as data in the layout.
|
||||
pub fn data_size_without_tag_id(&self, pointer_size: u32) -> Option<u32> {
|
||||
if !self.stores_tag_id_as_data(pointer_size) {
|
||||
pub fn data_size_without_tag_id(&self, target_info: TargetInfo) -> Option<u32> {
|
||||
if !self.stores_tag_id_as_data(target_info) {
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(
|
||||
self.data_size_and_alignment_help_match(None, pointer_size)
|
||||
.0,
|
||||
)
|
||||
Some(self.data_size_and_alignment_help_match(None, target_info).0)
|
||||
}
|
||||
|
||||
fn data_size_and_alignment_help_match(
|
||||
&self,
|
||||
id_data_layout: Option<Layout>,
|
||||
pointer_size: u32,
|
||||
target_info: TargetInfo,
|
||||
) -> (u32, u32) {
|
||||
match self {
|
||||
Self::NonRecursive(tags) => {
|
||||
Self::data_size_and_alignment_help(tags, id_data_layout, pointer_size)
|
||||
Self::data_size_and_alignment_help(tags, id_data_layout, target_info)
|
||||
}
|
||||
Self::Recursive(tags) => {
|
||||
Self::data_size_and_alignment_help(tags, id_data_layout, pointer_size)
|
||||
Self::data_size_and_alignment_help(tags, id_data_layout, target_info)
|
||||
}
|
||||
Self::NonNullableUnwrapped(fields) => {
|
||||
Self::data_size_and_alignment_help(&[fields], id_data_layout, pointer_size)
|
||||
Self::data_size_and_alignment_help(&[fields], id_data_layout, target_info)
|
||||
}
|
||||
Self::NullableWrapped { other_tags, .. } => {
|
||||
Self::data_size_and_alignment_help(other_tags, id_data_layout, pointer_size)
|
||||
Self::data_size_and_alignment_help(other_tags, id_data_layout, target_info)
|
||||
}
|
||||
Self::NullableUnwrapped { other_fields, .. } => {
|
||||
Self::data_size_and_alignment_help(&[other_fields], id_data_layout, pointer_size)
|
||||
Self::data_size_and_alignment_help(&[other_fields], id_data_layout, target_info)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -491,7 +488,7 @@ impl<'a> UnionLayout<'a> {
|
|||
fn data_size_and_alignment_help(
|
||||
variant_field_layouts: &[&[Layout]],
|
||||
id_data_layout: Option<Layout>,
|
||||
pointer_size: u32,
|
||||
target_info: TargetInfo,
|
||||
) -> (u32, u32) {
|
||||
let mut size = 0;
|
||||
let mut alignment_bytes = 0;
|
||||
|
@ -505,7 +502,7 @@ impl<'a> UnionLayout<'a> {
|
|||
data = Layout::Struct(&fields_and_id);
|
||||
}
|
||||
|
||||
let (variant_size, variant_alignment) = data.stack_size_and_alignment(pointer_size);
|
||||
let (variant_size, variant_alignment) = data.stack_size_and_alignment(target_info);
|
||||
alignment_bytes = alignment_bytes.max(variant_alignment);
|
||||
size = size.max(variant_size);
|
||||
}
|
||||
|
@ -700,7 +697,7 @@ impl<'a> LambdaSet<'a> {
|
|||
arena: &'a Bump,
|
||||
subs: &Subs,
|
||||
closure_var: Variable,
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
) -> Result<Self, LayoutProblem> {
|
||||
let mut tags = std::vec::Vec::new();
|
||||
match roc_types::pretty_print::chase_ext_tag_union(subs, closure_var, &mut tags) {
|
||||
|
@ -714,7 +711,7 @@ impl<'a> LambdaSet<'a> {
|
|||
arena,
|
||||
subs,
|
||||
seen: Vec::new_in(arena),
|
||||
ptr_bytes,
|
||||
target_info,
|
||||
};
|
||||
|
||||
for (tag_name, variables) in tags.iter() {
|
||||
|
@ -732,7 +729,7 @@ impl<'a> LambdaSet<'a> {
|
|||
}
|
||||
|
||||
let representation =
|
||||
arena.alloc(Self::make_representation(arena, subs, tags, ptr_bytes));
|
||||
arena.alloc(Self::make_representation(arena, subs, tags, target_info));
|
||||
|
||||
Ok(LambdaSet {
|
||||
set: set.into_bump_slice(),
|
||||
|
@ -755,10 +752,10 @@ impl<'a> LambdaSet<'a> {
|
|||
arena: &'a Bump,
|
||||
subs: &Subs,
|
||||
tags: std::vec::Vec<(TagName, std::vec::Vec<Variable>)>,
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
) -> Layout<'a> {
|
||||
// otherwise, this is a closure with a payload
|
||||
let variant = union_sorted_tags_help(arena, tags, None, subs, ptr_bytes);
|
||||
let variant = union_sorted_tags_help(arena, tags, None, subs, target_info);
|
||||
|
||||
use UnionVariant::*;
|
||||
match variant {
|
||||
|
@ -798,8 +795,8 @@ impl<'a> LambdaSet<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn stack_size(&self, pointer_size: u32) -> u32 {
|
||||
self.representation.stack_size(pointer_size)
|
||||
pub fn stack_size(&self, target_info: TargetInfo) -> u32 {
|
||||
self.representation.stack_size(target_info)
|
||||
}
|
||||
pub fn contains_refcounted(&self) -> bool {
|
||||
self.representation.contains_refcounted()
|
||||
|
@ -808,8 +805,8 @@ impl<'a> LambdaSet<'a> {
|
|||
self.representation.safe_to_memcpy()
|
||||
}
|
||||
|
||||
pub fn alignment_bytes(&self, pointer_size: u32) -> u32 {
|
||||
self.representation.alignment_bytes(pointer_size)
|
||||
pub fn alignment_bytes(&self, target_info: TargetInfo) -> u32 {
|
||||
self.representation.alignment_bytes(target_info)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -826,7 +823,7 @@ pub enum Builtin<'a> {
|
|||
}
|
||||
|
||||
pub struct Env<'a, 'b> {
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
arena: &'a Bump,
|
||||
seen: Vec<'a, Variable>,
|
||||
subs: &'b Subs,
|
||||
|
@ -898,7 +895,7 @@ impl<'a> Layout<'a> {
|
|||
}
|
||||
|
||||
Symbol::NUM_NAT | Symbol::NUM_NATURAL | Symbol::NUM_AT_NATURAL => {
|
||||
return Ok(Layout::usize(env.ptr_bytes))
|
||||
return Ok(Layout::usize(env.target_info))
|
||||
}
|
||||
|
||||
_ => Self::from_var(env, actual_var),
|
||||
|
@ -970,31 +967,31 @@ impl<'a> Layout<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn stack_size(&self, pointer_size: u32) -> u32 {
|
||||
let width = self.stack_size_without_alignment(pointer_size);
|
||||
let alignment = self.alignment_bytes(pointer_size);
|
||||
pub fn stack_size(&self, target_info: TargetInfo) -> u32 {
|
||||
let width = self.stack_size_without_alignment(target_info);
|
||||
let alignment = self.alignment_bytes(target_info);
|
||||
|
||||
round_up_to_alignment(width, alignment)
|
||||
}
|
||||
|
||||
pub fn stack_size_and_alignment(&self, pointer_size: u32) -> (u32, u32) {
|
||||
let width = self.stack_size_without_alignment(pointer_size);
|
||||
let alignment = self.alignment_bytes(pointer_size);
|
||||
pub fn stack_size_and_alignment(&self, target_info: TargetInfo) -> (u32, u32) {
|
||||
let width = self.stack_size_without_alignment(target_info);
|
||||
let alignment = self.alignment_bytes(target_info);
|
||||
|
||||
let size = round_up_to_alignment(width, alignment);
|
||||
(size, alignment)
|
||||
}
|
||||
|
||||
fn stack_size_without_alignment(&self, pointer_size: u32) -> u32 {
|
||||
fn stack_size_without_alignment(&self, target_info: TargetInfo) -> u32 {
|
||||
use Layout::*;
|
||||
|
||||
match self {
|
||||
Builtin(builtin) => builtin.stack_size(pointer_size),
|
||||
Builtin(builtin) => builtin.stack_size(target_info),
|
||||
Struct(fields) => {
|
||||
let mut sum = 0;
|
||||
|
||||
for field_layout in *fields {
|
||||
sum += field_layout.stack_size(pointer_size);
|
||||
sum += field_layout.stack_size(target_info);
|
||||
}
|
||||
|
||||
sum
|
||||
|
@ -1003,26 +1000,26 @@ impl<'a> Layout<'a> {
|
|||
use UnionLayout::*;
|
||||
|
||||
match variant {
|
||||
NonRecursive(_) => variant.data_size_and_alignment(pointer_size).0,
|
||||
NonRecursive(_) => variant.data_size_and_alignment(target_info).0,
|
||||
|
||||
Recursive(_)
|
||||
| NullableWrapped { .. }
|
||||
| NullableUnwrapped { .. }
|
||||
| NonNullableUnwrapped(_) => pointer_size,
|
||||
| NonNullableUnwrapped(_) => target_info.ptr_width() as u32,
|
||||
}
|
||||
}
|
||||
LambdaSet(lambda_set) => lambda_set
|
||||
.runtime_representation()
|
||||
.stack_size_without_alignment(pointer_size),
|
||||
RecursivePointer => pointer_size,
|
||||
.stack_size_without_alignment(target_info),
|
||||
RecursivePointer => target_info.ptr_width() as u32,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alignment_bytes(&self, pointer_size: u32) -> u32 {
|
||||
pub fn alignment_bytes(&self, target_info: TargetInfo) -> u32 {
|
||||
match self {
|
||||
Layout::Struct(fields) => fields
|
||||
.iter()
|
||||
.map(|x| x.alignment_bytes(pointer_size))
|
||||
.map(|x| x.alignment_bytes(target_info))
|
||||
.max()
|
||||
.unwrap_or(0),
|
||||
|
||||
|
@ -1036,44 +1033,44 @@ impl<'a> Layout<'a> {
|
|||
.flat_map(|layouts| {
|
||||
layouts
|
||||
.iter()
|
||||
.map(|layout| layout.alignment_bytes(pointer_size))
|
||||
.map(|layout| layout.alignment_bytes(target_info))
|
||||
})
|
||||
.max();
|
||||
|
||||
let tag_id_builtin = variant.tag_id_builtin();
|
||||
match max_alignment {
|
||||
Some(align) => round_up_to_alignment(
|
||||
align.max(tag_id_builtin.alignment_bytes(pointer_size)),
|
||||
tag_id_builtin.alignment_bytes(pointer_size),
|
||||
align.max(tag_id_builtin.alignment_bytes(target_info)),
|
||||
tag_id_builtin.alignment_bytes(target_info),
|
||||
),
|
||||
None => {
|
||||
// none of the tags had any payload, but the tag id still contains information
|
||||
tag_id_builtin.alignment_bytes(pointer_size)
|
||||
tag_id_builtin.alignment_bytes(target_info)
|
||||
}
|
||||
}
|
||||
}
|
||||
Recursive(_)
|
||||
| NullableWrapped { .. }
|
||||
| NullableUnwrapped { .. }
|
||||
| NonNullableUnwrapped(_) => pointer_size,
|
||||
| NonNullableUnwrapped(_) => target_info.ptr_width() as u32,
|
||||
}
|
||||
}
|
||||
Layout::LambdaSet(lambda_set) => lambda_set
|
||||
.runtime_representation()
|
||||
.alignment_bytes(pointer_size),
|
||||
Layout::Builtin(builtin) => builtin.alignment_bytes(pointer_size),
|
||||
Layout::RecursivePointer => pointer_size,
|
||||
.alignment_bytes(target_info),
|
||||
Layout::Builtin(builtin) => builtin.alignment_bytes(target_info),
|
||||
Layout::RecursivePointer => target_info.ptr_width() as u32,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn allocation_alignment_bytes(&self, pointer_size: u32) -> u32 {
|
||||
pub fn allocation_alignment_bytes(&self, target_info: TargetInfo) -> u32 {
|
||||
match self {
|
||||
Layout::Builtin(builtin) => builtin.allocation_alignment_bytes(pointer_size),
|
||||
Layout::Builtin(builtin) => builtin.allocation_alignment_bytes(target_info),
|
||||
Layout::Struct(_) => unreachable!("not heap-allocated"),
|
||||
Layout::Union(union_layout) => union_layout.allocation_alignment_bytes(pointer_size),
|
||||
Layout::Union(union_layout) => union_layout.allocation_alignment_bytes(target_info),
|
||||
Layout::LambdaSet(lambda_set) => lambda_set
|
||||
.runtime_representation()
|
||||
.allocation_alignment_bytes(pointer_size),
|
||||
.allocation_alignment_bytes(target_info),
|
||||
Layout::RecursivePointer => unreachable!("should be looked up to get an actual layout"),
|
||||
}
|
||||
}
|
||||
|
@ -1157,7 +1154,7 @@ impl<'a> Layout<'a> {
|
|||
/// But if we're careful when to invalidate certain keys, we still get some benefit
|
||||
#[derive(Debug)]
|
||||
pub struct LayoutCache<'a> {
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
_marker: std::marker::PhantomData<&'a u8>,
|
||||
}
|
||||
|
||||
|
@ -1169,9 +1166,9 @@ pub enum CachedLayout<'a> {
|
|||
}
|
||||
|
||||
impl<'a> LayoutCache<'a> {
|
||||
pub fn new(ptr_bytes: u32) -> Self {
|
||||
pub fn new(target_info: TargetInfo) -> Self {
|
||||
Self {
|
||||
ptr_bytes,
|
||||
target_info,
|
||||
_marker: Default::default(),
|
||||
}
|
||||
}
|
||||
|
@ -1189,7 +1186,7 @@ impl<'a> LayoutCache<'a> {
|
|||
arena,
|
||||
subs,
|
||||
seen: Vec::new_in(arena),
|
||||
ptr_bytes: self.ptr_bytes,
|
||||
target_info: self.target_info,
|
||||
};
|
||||
|
||||
Layout::from_var(&mut env, var)
|
||||
|
@ -1208,7 +1205,7 @@ impl<'a> LayoutCache<'a> {
|
|||
arena,
|
||||
subs,
|
||||
seen: Vec::new_in(arena),
|
||||
ptr_bytes: self.ptr_bytes,
|
||||
target_info: self.target_info,
|
||||
};
|
||||
RawFunctionLayout::from_var(&mut env, var)
|
||||
}
|
||||
|
@ -1240,11 +1237,17 @@ impl<'a> Layout<'a> {
|
|||
Layout::Builtin(Builtin::Float(FloatWidth::F32))
|
||||
}
|
||||
|
||||
pub fn usize(ptr_bytes: u32) -> Layout<'a> {
|
||||
match ptr_bytes {
|
||||
4 => Self::u32(),
|
||||
8 => Self::u64(),
|
||||
_ => panic!("width of usize {} not supported", ptr_bytes),
|
||||
pub fn usize(target_info: TargetInfo) -> Layout<'a> {
|
||||
match target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes4 => Self::u32(),
|
||||
roc_target::PtrWidth::Bytes8 => Self::u64(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn isize(target_info: TargetInfo) -> Layout<'a> {
|
||||
match target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes4 => Self::i32(),
|
||||
roc_target::PtrWidth::Bytes8 => Self::i64(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1318,42 +1321,46 @@ impl<'a> Builtin<'a> {
|
|||
pub const WRAPPER_PTR: u32 = 0;
|
||||
pub const WRAPPER_LEN: u32 = 1;
|
||||
|
||||
pub fn stack_size(&self, pointer_size: u32) -> u32 {
|
||||
pub fn stack_size(&self, target_info: TargetInfo) -> u32 {
|
||||
use Builtin::*;
|
||||
|
||||
let ptr_width = target_info.ptr_width() as u32;
|
||||
|
||||
match self {
|
||||
Int(int) => int.stack_size(),
|
||||
Float(float) => float.stack_size(),
|
||||
Bool => Builtin::I1_SIZE,
|
||||
Decimal => Builtin::DECIMAL_SIZE,
|
||||
Str => Builtin::STR_WORDS * pointer_size,
|
||||
Dict(_, _) => Builtin::DICT_WORDS * pointer_size,
|
||||
Set(_) => Builtin::SET_WORDS * pointer_size,
|
||||
List(_) => Builtin::LIST_WORDS * pointer_size,
|
||||
Str => Builtin::STR_WORDS * ptr_width,
|
||||
Dict(_, _) => Builtin::DICT_WORDS * ptr_width,
|
||||
Set(_) => Builtin::SET_WORDS * ptr_width,
|
||||
List(_) => Builtin::LIST_WORDS * ptr_width,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alignment_bytes(&self, pointer_size: u32) -> u32 {
|
||||
pub fn alignment_bytes(&self, target_info: TargetInfo) -> u32 {
|
||||
use std::mem::align_of;
|
||||
use Builtin::*;
|
||||
|
||||
let ptr_width = target_info.ptr_width() as u32;
|
||||
|
||||
// for our data structures, what counts is the alignment of the `( ptr, len )` tuple, and
|
||||
// since both of those are one pointer size, the alignment of that structure is a pointer
|
||||
// size
|
||||
match self {
|
||||
Int(int_width) => int_width.alignment_bytes(),
|
||||
Float(float_width) => float_width.alignment_bytes(),
|
||||
Int(int_width) => int_width.alignment_bytes(target_info),
|
||||
Float(float_width) => float_width.alignment_bytes(target_info),
|
||||
Bool => align_of::<bool>() as u32,
|
||||
Decimal => align_of::<i128>() as u32,
|
||||
Dict(_, _) => pointer_size,
|
||||
Set(_) => pointer_size,
|
||||
Decimal => IntWidth::I128.alignment_bytes(target_info),
|
||||
Dict(_, _) => ptr_width,
|
||||
Set(_) => ptr_width,
|
||||
// we often treat these as i128 (64-bit systems)
|
||||
// or i64 (32-bit systems).
|
||||
//
|
||||
// In webassembly, For that to be safe
|
||||
// they must be aligned to allow such access
|
||||
List(_) => pointer_size,
|
||||
Str => pointer_size,
|
||||
List(_) => ptr_width,
|
||||
Str => ptr_width,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1433,21 +1440,23 @@ impl<'a> Builtin<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn allocation_alignment_bytes(&self, pointer_size: u32) -> u32 {
|
||||
pub fn allocation_alignment_bytes(&self, target_info: TargetInfo) -> u32 {
|
||||
let ptr_width = target_info.ptr_width() as u32;
|
||||
|
||||
let allocation = match self {
|
||||
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal => {
|
||||
unreachable!("not heap-allocated")
|
||||
}
|
||||
Builtin::Str => pointer_size,
|
||||
Builtin::Str => ptr_width,
|
||||
Builtin::Dict(k, v) => k
|
||||
.alignment_bytes(pointer_size)
|
||||
.max(v.alignment_bytes(pointer_size))
|
||||
.max(pointer_size),
|
||||
Builtin::Set(k) => k.alignment_bytes(pointer_size).max(pointer_size),
|
||||
Builtin::List(e) => e.alignment_bytes(pointer_size).max(pointer_size),
|
||||
.alignment_bytes(target_info)
|
||||
.max(v.alignment_bytes(target_info))
|
||||
.max(ptr_width),
|
||||
Builtin::Set(k) => k.alignment_bytes(target_info).max(ptr_width),
|
||||
Builtin::List(e) => e.alignment_bytes(target_info).max(ptr_width),
|
||||
};
|
||||
|
||||
allocation.max(pointer_size)
|
||||
allocation.max(ptr_width)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1459,7 +1468,7 @@ fn layout_from_flat_type<'a>(
|
|||
|
||||
let arena = env.arena;
|
||||
let subs = env.subs;
|
||||
let ptr_bytes = env.ptr_bytes;
|
||||
let target_info = env.target_info;
|
||||
|
||||
match flat_type {
|
||||
Apply(symbol, args) => {
|
||||
|
@ -1469,7 +1478,7 @@ fn layout_from_flat_type<'a>(
|
|||
// Ints
|
||||
Symbol::NUM_NAT => {
|
||||
debug_assert_eq!(args.len(), 0);
|
||||
Ok(Layout::usize(env.ptr_bytes))
|
||||
Ok(Layout::usize(env.target_info))
|
||||
}
|
||||
|
||||
Symbol::NUM_I128 => {
|
||||
|
@ -1535,7 +1544,7 @@ fn layout_from_flat_type<'a>(
|
|||
let var = args[0];
|
||||
let content = subs.get_content_without_compacting(var);
|
||||
|
||||
layout_from_num_content(content)
|
||||
layout_from_num_content(content, target_info)
|
||||
}
|
||||
|
||||
Symbol::STR_STR => Ok(Layout::Builtin(Builtin::Str)),
|
||||
|
@ -1551,7 +1560,8 @@ fn layout_from_flat_type<'a>(
|
|||
}
|
||||
}
|
||||
Func(_, closure_var, _) => {
|
||||
let lambda_set = LambdaSet::from_var(env.arena, env.subs, closure_var, env.ptr_bytes)?;
|
||||
let lambda_set =
|
||||
LambdaSet::from_var(env.arena, env.subs, closure_var, env.target_info)?;
|
||||
|
||||
Ok(Layout::LambdaSet(lambda_set))
|
||||
}
|
||||
|
@ -1571,8 +1581,8 @@ fn layout_from_flat_type<'a>(
|
|||
}
|
||||
|
||||
pairs.sort_by(|(label1, layout1), (label2, layout2)| {
|
||||
let size1 = layout1.alignment_bytes(ptr_bytes);
|
||||
let size2 = layout2.alignment_bytes(ptr_bytes);
|
||||
let size1 = layout1.alignment_bytes(target_info);
|
||||
let size2 = layout2.alignment_bytes(target_info);
|
||||
|
||||
size2.cmp(&size1).then(label1.cmp(label2))
|
||||
});
|
||||
|
@ -1592,7 +1602,7 @@ fn layout_from_flat_type<'a>(
|
|||
|
||||
debug_assert!(ext_var_is_empty_tag_union(subs, ext_var));
|
||||
|
||||
Ok(layout_from_tag_union(arena, &tags, subs, env.ptr_bytes))
|
||||
Ok(layout_from_tag_union(arena, &tags, subs, env.target_info))
|
||||
}
|
||||
FunctionOrTagUnion(tag_name, _, ext_var) => {
|
||||
debug_assert!(
|
||||
|
@ -1603,7 +1613,7 @@ fn layout_from_flat_type<'a>(
|
|||
let union_tags = UnionTags::from_tag_name_index(tag_name);
|
||||
let (tags, _) = union_tags.unsorted_tags_and_ext(subs, ext_var);
|
||||
|
||||
Ok(layout_from_tag_union(arena, &tags, subs, env.ptr_bytes))
|
||||
Ok(layout_from_tag_union(arena, &tags, subs, env.target_info))
|
||||
}
|
||||
RecursiveTagUnion(rec_var, tags, ext_var) => {
|
||||
let (tags, ext_var) = tags.unsorted_tags_and_ext(subs, ext_var);
|
||||
|
@ -1653,8 +1663,8 @@ fn layout_from_flat_type<'a>(
|
|||
}
|
||||
|
||||
tag_layout.sort_by(|layout1, layout2| {
|
||||
let size1 = layout1.alignment_bytes(ptr_bytes);
|
||||
let size2 = layout2.alignment_bytes(ptr_bytes);
|
||||
let size1 = layout1.alignment_bytes(target_info);
|
||||
let size2 = layout2.alignment_bytes(target_info);
|
||||
|
||||
size2.cmp(&size1)
|
||||
});
|
||||
|
@ -1699,13 +1709,13 @@ pub fn sort_record_fields<'a>(
|
|||
arena: &'a Bump,
|
||||
var: Variable,
|
||||
subs: &Subs,
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
) -> Result<Vec<'a, SortedField<'a>>, LayoutProblem> {
|
||||
let mut env = Env {
|
||||
arena,
|
||||
subs,
|
||||
seen: Vec::new_in(arena),
|
||||
ptr_bytes,
|
||||
target_info,
|
||||
};
|
||||
|
||||
let (it, _) = match gather_fields_unsorted_iter(subs, RecordFields::empty(), var) {
|
||||
|
@ -1724,7 +1734,7 @@ fn sort_record_fields_help<'a>(
|
|||
env: &mut Env<'a, '_>,
|
||||
fields_map: impl Iterator<Item = (Lowercase, RecordField<Variable>)>,
|
||||
) -> Result<Vec<'a, SortedField<'a>>, LayoutProblem> {
|
||||
let ptr_bytes = env.ptr_bytes;
|
||||
let target_info = env.target_info;
|
||||
|
||||
// Sort the fields by label
|
||||
let mut sorted_fields = Vec::with_capacity_in(fields_map.size_hint().0, env.arena);
|
||||
|
@ -1746,8 +1756,8 @@ fn sort_record_fields_help<'a>(
|
|||
|(label1, _, res_layout1), (label2, _, res_layout2)| match res_layout1 {
|
||||
Ok(layout1) | Err(layout1) => match res_layout2 {
|
||||
Ok(layout2) | Err(layout2) => {
|
||||
let size1 = layout1.alignment_bytes(ptr_bytes);
|
||||
let size2 = layout2.alignment_bytes(ptr_bytes);
|
||||
let size1 = layout1.alignment_bytes(target_info);
|
||||
let size2 = layout2.alignment_bytes(target_info);
|
||||
|
||||
size2.cmp(&size1).then(label1.cmp(label2))
|
||||
}
|
||||
|
@ -1881,7 +1891,7 @@ pub fn union_sorted_tags<'a>(
|
|||
arena: &'a Bump,
|
||||
var: Variable,
|
||||
subs: &Subs,
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
) -> Result<UnionVariant<'a>, LayoutProblem> {
|
||||
let var =
|
||||
if let Content::RecursionVar { structure, .. } = subs.get_content_without_compacting(var) {
|
||||
|
@ -1894,7 +1904,7 @@ pub fn union_sorted_tags<'a>(
|
|||
let result = match roc_types::pretty_print::chase_ext_tag_union(subs, var, &mut tags_vec) {
|
||||
Ok(()) | Err((_, Content::FlexVar(_))) | Err((_, Content::RecursionVar { .. })) => {
|
||||
let opt_rec_var = get_recursion_var(subs, var);
|
||||
union_sorted_tags_help(arena, tags_vec, opt_rec_var, subs, ptr_bytes)
|
||||
union_sorted_tags_help(arena, tags_vec, opt_rec_var, subs, target_info)
|
||||
}
|
||||
Err((_, Content::Error)) => return Err(LayoutProblem::Erroneous),
|
||||
Err(other) => panic!("invalid content in tag union variable: {:?}", other),
|
||||
|
@ -1928,7 +1938,7 @@ fn union_sorted_tags_help_new<'a>(
|
|||
tags_list: &[(&'_ TagName, &[Variable])],
|
||||
opt_rec_var: Option<Variable>,
|
||||
subs: &Subs,
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
) -> UnionVariant<'a> {
|
||||
// sort up front; make sure the ordering stays intact!
|
||||
let mut tags_list = Vec::from_iter_in(tags_list.iter(), arena);
|
||||
|
@ -1938,7 +1948,7 @@ fn union_sorted_tags_help_new<'a>(
|
|||
arena,
|
||||
subs,
|
||||
seen: Vec::new_in(arena),
|
||||
ptr_bytes,
|
||||
target_info,
|
||||
};
|
||||
|
||||
match tags_list.len() {
|
||||
|
@ -1957,7 +1967,8 @@ fn union_sorted_tags_help_new<'a>(
|
|||
match tag_name {
|
||||
TagName::Private(Symbol::NUM_AT_NUM) => {
|
||||
let var = arguments[0];
|
||||
layouts.push(unwrap_num_tag(subs, var, ptr_bytes).expect("invalid num layout"));
|
||||
layouts
|
||||
.push(unwrap_num_tag(subs, var, target_info).expect("invalid num layout"));
|
||||
}
|
||||
_ => {
|
||||
for &var in arguments {
|
||||
|
@ -1981,8 +1992,8 @@ fn union_sorted_tags_help_new<'a>(
|
|||
}
|
||||
|
||||
layouts.sort_by(|layout1, layout2| {
|
||||
let size1 = layout1.alignment_bytes(ptr_bytes);
|
||||
let size2 = layout2.alignment_bytes(ptr_bytes);
|
||||
let size1 = layout1.alignment_bytes(target_info);
|
||||
let size2 = layout2.alignment_bytes(target_info);
|
||||
|
||||
size2.cmp(&size1)
|
||||
});
|
||||
|
@ -2059,8 +2070,8 @@ fn union_sorted_tags_help_new<'a>(
|
|||
}
|
||||
|
||||
arg_layouts.sort_by(|layout1, layout2| {
|
||||
let size1 = layout1.alignment_bytes(ptr_bytes);
|
||||
let size2 = layout2.alignment_bytes(ptr_bytes);
|
||||
let size1 = layout1.alignment_bytes(target_info);
|
||||
let size2 = layout2.alignment_bytes(target_info);
|
||||
|
||||
size2.cmp(&size1)
|
||||
});
|
||||
|
@ -2131,7 +2142,7 @@ pub fn union_sorted_tags_help<'a>(
|
|||
mut tags_vec: std::vec::Vec<(TagName, std::vec::Vec<Variable>)>,
|
||||
opt_rec_var: Option<Variable>,
|
||||
subs: &Subs,
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
) -> UnionVariant<'a> {
|
||||
// sort up front; make sure the ordering stays intact!
|
||||
tags_vec.sort_unstable_by(|(a, _), (b, _)| a.cmp(b));
|
||||
|
@ -2140,7 +2151,7 @@ pub fn union_sorted_tags_help<'a>(
|
|||
arena,
|
||||
subs,
|
||||
seen: Vec::new_in(arena),
|
||||
ptr_bytes,
|
||||
target_info,
|
||||
};
|
||||
|
||||
match tags_vec.len() {
|
||||
|
@ -2159,7 +2170,8 @@ pub fn union_sorted_tags_help<'a>(
|
|||
match tag_name {
|
||||
TagName::Private(Symbol::NUM_AT_NUM) => {
|
||||
layouts.push(
|
||||
unwrap_num_tag(subs, arguments[0], ptr_bytes).expect("invalid num layout"),
|
||||
unwrap_num_tag(subs, arguments[0], target_info)
|
||||
.expect("invalid num layout"),
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
|
@ -2189,8 +2201,8 @@ pub fn union_sorted_tags_help<'a>(
|
|||
}
|
||||
|
||||
layouts.sort_by(|layout1, layout2| {
|
||||
let size1 = layout1.alignment_bytes(ptr_bytes);
|
||||
let size2 = layout2.alignment_bytes(ptr_bytes);
|
||||
let size1 = layout1.alignment_bytes(target_info);
|
||||
let size2 = layout2.alignment_bytes(target_info);
|
||||
|
||||
size2.cmp(&size1)
|
||||
});
|
||||
|
@ -2272,8 +2284,8 @@ pub fn union_sorted_tags_help<'a>(
|
|||
}
|
||||
|
||||
arg_layouts.sort_by(|layout1, layout2| {
|
||||
let size1 = layout1.alignment_bytes(ptr_bytes);
|
||||
let size2 = layout2.alignment_bytes(ptr_bytes);
|
||||
let size1 = layout1.alignment_bytes(target_info);
|
||||
let size2 = layout2.alignment_bytes(target_info);
|
||||
|
||||
size2.cmp(&size1)
|
||||
});
|
||||
|
@ -2343,20 +2355,20 @@ fn layout_from_newtype<'a>(
|
|||
arena: &'a Bump,
|
||||
tags: &UnsortedUnionTags,
|
||||
subs: &Subs,
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
) -> Layout<'a> {
|
||||
debug_assert!(tags.is_newtype_wrapper(subs));
|
||||
|
||||
let (tag_name, var) = tags.get_newtype(subs);
|
||||
|
||||
if tag_name == &TagName::Private(Symbol::NUM_AT_NUM) {
|
||||
unwrap_num_tag(subs, var, ptr_bytes).expect("invalid Num argument")
|
||||
unwrap_num_tag(subs, var, target_info).expect("invalid Num argument")
|
||||
} else {
|
||||
let mut env = Env {
|
||||
arena,
|
||||
subs,
|
||||
seen: Vec::new_in(arena),
|
||||
ptr_bytes,
|
||||
target_info,
|
||||
};
|
||||
|
||||
match Layout::from_var(&mut env, var) {
|
||||
|
@ -2380,12 +2392,12 @@ fn layout_from_tag_union<'a>(
|
|||
arena: &'a Bump,
|
||||
tags: &UnsortedUnionTags,
|
||||
subs: &Subs,
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
) -> Layout<'a> {
|
||||
use UnionVariant::*;
|
||||
|
||||
if tags.is_newtype_wrapper(subs) {
|
||||
return layout_from_newtype(arena, tags, subs, ptr_bytes);
|
||||
return layout_from_newtype(arena, tags, subs, target_info);
|
||||
}
|
||||
|
||||
let tags_vec = &tags.tags;
|
||||
|
@ -2396,11 +2408,12 @@ fn layout_from_tag_union<'a>(
|
|||
|
||||
let &var = arguments.iter().next().unwrap();
|
||||
|
||||
unwrap_num_tag(subs, var, ptr_bytes).expect("invalid Num argument")
|
||||
unwrap_num_tag(subs, var, target_info).expect("invalid Num argument")
|
||||
}
|
||||
_ => {
|
||||
let opt_rec_var = None;
|
||||
let variant = union_sorted_tags_help_new(arena, tags_vec, opt_rec_var, subs, ptr_bytes);
|
||||
let variant =
|
||||
union_sorted_tags_help_new(arena, tags_vec, opt_rec_var, subs, target_info);
|
||||
|
||||
match variant {
|
||||
Never => Layout::VOID,
|
||||
|
@ -2498,12 +2511,13 @@ pub fn ext_var_is_empty_tag_union(_: &Subs, _: Variable) -> bool {
|
|||
unreachable!();
|
||||
}
|
||||
|
||||
fn layout_from_num_content<'a>(content: &Content) -> Result<Layout<'a>, LayoutProblem> {
|
||||
fn layout_from_num_content<'a>(
|
||||
content: &Content,
|
||||
target_info: TargetInfo,
|
||||
) -> Result<Layout<'a>, LayoutProblem> {
|
||||
use roc_types::subs::Content::*;
|
||||
use roc_types::subs::FlatType::*;
|
||||
|
||||
let ptr_bytes = 8;
|
||||
|
||||
match content {
|
||||
RecursionVar { .. } => panic!("recursion var in num"),
|
||||
FlexVar(_) | RigidVar(_) => {
|
||||
|
@ -2515,7 +2529,7 @@ fn layout_from_num_content<'a>(content: &Content) -> Result<Layout<'a>, LayoutPr
|
|||
}
|
||||
Structure(Apply(symbol, args)) => match *symbol {
|
||||
// Ints
|
||||
Symbol::NUM_NAT => Ok(Layout::usize(ptr_bytes)),
|
||||
Symbol::NUM_NAT => Ok(Layout::usize(target_info)),
|
||||
|
||||
Symbol::NUM_INTEGER => Ok(Layout::i64()),
|
||||
Symbol::NUM_I128 => Ok(Layout::i128()),
|
||||
|
@ -2558,7 +2572,7 @@ fn layout_from_num_content<'a>(content: &Content) -> Result<Layout<'a>, LayoutPr
|
|||
fn unwrap_num_tag<'a>(
|
||||
subs: &Subs,
|
||||
var: Variable,
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
) -> Result<Layout<'a>, LayoutProblem> {
|
||||
match subs.get_content_without_compacting(var) {
|
||||
Content::Alias(Symbol::NUM_INTEGER, args, _) => {
|
||||
|
@ -2583,7 +2597,7 @@ fn unwrap_num_tag<'a>(
|
|||
Symbol::NUM_UNSIGNED32 => Layout::u32(),
|
||||
Symbol::NUM_UNSIGNED16 => Layout::u16(),
|
||||
Symbol::NUM_UNSIGNED8 => Layout::u8(),
|
||||
Symbol::NUM_NATURAL => Layout::usize(ptr_bytes),
|
||||
Symbol::NUM_NATURAL => Layout::usize(target_info),
|
||||
|
||||
_ => unreachable!("not a valid int variant: {:?} {:?}", symbol, args),
|
||||
};
|
||||
|
@ -2829,8 +2843,8 @@ mod test {
|
|||
|
||||
let layout = Layout::Union(UnionLayout::NonRecursive(&tt));
|
||||
|
||||
let ptr_width = 8;
|
||||
assert_eq!(layout.stack_size(ptr_width), 1);
|
||||
assert_eq!(layout.alignment_bytes(ptr_width), 1);
|
||||
let target_info = TargetInfo::default_x86_64();
|
||||
assert_eq!(layout.stack_size(target_info), 1);
|
||||
assert_eq!(layout.alignment_bytes(target_info), 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
|||
use roc_collections::all::MutMap;
|
||||
use roc_module::ident::TagName;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_target::TargetInfo;
|
||||
use roc_types::subs::{Content, FlatType, Subs, Variable};
|
||||
use roc_types::types::RecordField;
|
||||
use std::collections::hash_map::Entry;
|
||||
|
@ -99,7 +100,7 @@ pub struct Layouts {
|
|||
lambda_sets: Vec<LambdaSet>,
|
||||
symbols: Vec<Symbol>,
|
||||
recursion_variable_to_structure_variable_map: MutMap<Variable, Index<Layout>>,
|
||||
usize_int_width: IntWidth,
|
||||
target_info: TargetInfo,
|
||||
}
|
||||
|
||||
pub struct FunctionLayout {
|
||||
|
@ -402,7 +403,7 @@ impl Layouts {
|
|||
const VOID_TUPLE: Index<(Layout, Layout)> = Index::new(0);
|
||||
const UNIT_INDEX: Index<Layout> = Index::new(2);
|
||||
|
||||
pub fn new(usize_int_width: IntWidth) -> Self {
|
||||
pub fn new(target_info: TargetInfo) -> Self {
|
||||
let mut layouts = Vec::with_capacity(64);
|
||||
|
||||
layouts.push(Layout::VOID);
|
||||
|
@ -420,7 +421,7 @@ impl Layouts {
|
|||
lambda_sets: Vec::default(),
|
||||
symbols: Vec::default(),
|
||||
recursion_variable_to_structure_variable_map: MutMap::default(),
|
||||
usize_int_width,
|
||||
target_info,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -443,7 +444,12 @@ impl Layouts {
|
|||
}
|
||||
|
||||
fn usize(&self) -> Layout {
|
||||
Layout::Int(self.usize_int_width)
|
||||
let usize_int_width = match self.target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes4 => IntWidth::U32,
|
||||
roc_target::PtrWidth::Bytes8 => IntWidth::U64,
|
||||
};
|
||||
|
||||
Layout::Int(usize_int_width)
|
||||
}
|
||||
|
||||
fn align_of_layout_index(&self, index: Index<Layout>) -> u16 {
|
||||
|
@ -453,18 +459,23 @@ impl Layouts {
|
|||
}
|
||||
|
||||
fn align_of_layout(&self, layout: Layout) -> u16 {
|
||||
let ptr_alignment = self.usize_int_width.alignment_bytes() as u16;
|
||||
let usize_int_width = match self.target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes4 => IntWidth::U32,
|
||||
roc_target::PtrWidth::Bytes8 => IntWidth::U64,
|
||||
};
|
||||
|
||||
let ptr_alignment = usize_int_width.alignment_bytes(self.target_info) as u16;
|
||||
|
||||
match layout {
|
||||
Layout::Reserved => unreachable!(),
|
||||
Layout::Int(int_width) => int_width.alignment_bytes() as u16,
|
||||
Layout::Float(float_width) => float_width.alignment_bytes() as u16,
|
||||
Layout::Decimal => IntWidth::U128.alignment_bytes() as u16,
|
||||
Layout::Int(int_width) => int_width.alignment_bytes(self.target_info) as u16,
|
||||
Layout::Float(float_width) => float_width.alignment_bytes(self.target_info) as u16,
|
||||
Layout::Decimal => IntWidth::U128.alignment_bytes(self.target_info) as u16,
|
||||
Layout::Str | Layout::Dict(_) | Layout::Set(_) | Layout::List(_) => ptr_alignment,
|
||||
Layout::Struct(slice) => self.align_of_layout_slice(slice),
|
||||
Layout::Boxed(_) | Layout::UnionRecursive(_) => ptr_alignment,
|
||||
Layout::UnionNonRecursive(slices) => {
|
||||
let tag_id_align = IntWidth::I64.alignment_bytes() as u16;
|
||||
let tag_id_align = IntWidth::I64.alignment_bytes(self.target_info) as u16;
|
||||
|
||||
self.align_of_layout_slices(slices).max(tag_id_align)
|
||||
}
|
||||
|
@ -518,7 +529,12 @@ impl Layouts {
|
|||
}
|
||||
|
||||
pub fn size_of_layout(&self, layout: Layout) -> u16 {
|
||||
let ptr_width = self.usize_int_width.stack_size() as u16;
|
||||
let usize_int_width = match self.target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes4 => IntWidth::U32,
|
||||
roc_target::PtrWidth::Bytes8 => IntWidth::U64,
|
||||
};
|
||||
|
||||
let ptr_width = usize_int_width.stack_size() as u16;
|
||||
|
||||
match layout {
|
||||
Layout::Reserved => unreachable!(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue