fix bug where incorrect stack size is given

This commit is contained in:
Folkert 2022-03-30 17:25:28 +02:00
parent c73c01aa34
commit fd209f90ff
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
5 changed files with 93 additions and 41 deletions

View file

@ -131,30 +131,28 @@ fn call_bitcode_fn_help<'a, 'ctx, 'env>(
let call = env.builder.build_call(fn_val, &arguments, "call_builtin");
for i in 0..fn_val.count_params() {
let attributes = fn_val.attributes(AttributeLoc::Param(i));
for attribute in attributes {
if attribute.is_type() {}
call.add_attribute(AttributeLoc::Param(i), attribute)
}
}
match fn_name {
bitcode::STR_NUMBER_OF_BYTES | bitcode::STR_COUNT_GRAPEHEME_CLUSTERS => {
// hacks
string_argument(env, call, 0);
}
bitcode::STR_ENDS_WITH | bitcode::STR_STARTS_WITH => {
string_argument(env, call, 0);
string_argument(env, call, 1);
}
bitcode::STR_STR_SPLIT_IN_PLACE => {
string_argument(env, call, 0);
string_argument(env, call, 1);
let i = 0;
call.add_attribute(
AttributeLoc::Param(0),
type_attribute(env.context, "byval", zig_str_type(env).into()),
);
call.add_attribute(
AttributeLoc::Param(i as u32),
enum_attribute(env.context, "nonnull"),
);
call.add_attribute(
AttributeLoc::Param(i as u32),
enum_attribute(env.context, "nocapture"),
);
call.add_attribute(
AttributeLoc::Param(i as u32),
enum_attribute(env.context, "readonly"),
);
dbg!(fn_val.get_type());
}
_ => {}
}
@ -163,6 +161,32 @@ fn call_bitcode_fn_help<'a, 'ctx, 'env>(
call
}
fn string_argument<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
call: CallSiteValue,
parameter_index: u32,
) {
call.add_attribute(
AttributeLoc::Param(0),
type_attribute(env.context, "byval", zig_str_type(env).into()),
);
call.add_attribute(
AttributeLoc::Param(parameter_index as u32),
enum_attribute(env.context, "nonnull"),
);
call.add_attribute(
AttributeLoc::Param(parameter_index as u32),
enum_attribute(env.context, "nocapture"),
);
call.add_attribute(
AttributeLoc::Param(parameter_index as u32),
enum_attribute(env.context, "readonly"),
);
}
pub fn call_bitcode_fn_fixing_for_convention<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
args: &[BasicValueEnum<'ctx>],

View file

@ -18,5 +18,5 @@ roc_collections = { path = "../collections" }
roc_load_internal = { path = "../load_internal" }
roc_builtins = { path = "../builtins" }
roc_module = { path = "../module" }
bumpalo = { version = "3.8.0", features = ["collections"] }
roc_target = { path = "../roc_target" }
bumpalo = { version = "3.8.0", features = ["collections"] }

View file

@ -554,6 +554,31 @@ impl<'a> UnionLayout<'a> {
(size, alignment_bytes)
}
/// Very important to use this when doing a memcpy!
fn stack_size_without_alignment(&self, target_info: TargetInfo) -> u32 {
match self {
UnionLayout::NonRecursive(tags) => {
let id_layout = self.tag_id_layout();
let mut size = 0;
for field_layouts in tags.iter() {
let fields = Layout::struct_no_name_order(field_layouts);
let fields_and_id = [fields, id_layout];
let data = Layout::struct_no_name_order(&fields_and_id);
size = size.max(data.stack_size_without_alignment(target_info));
}
size
}
UnionLayout::Recursive(_)
| UnionLayout::NonNullableUnwrapped(_)
| UnionLayout::NullableWrapped { .. }
| UnionLayout::NullableUnwrapped { .. } => target_info.ptr_width() as u32,
}
}
}
/// Custom type so we can get the numeric representation of a symbol in tests (so `#UserApp.3`
@ -1042,7 +1067,8 @@ impl<'a> Layout<'a> {
(size, alignment)
}
fn stack_size_without_alignment(&self, target_info: TargetInfo) -> u32 {
/// Very important to use this when doing a memcpy!
pub fn stack_size_without_alignment(&self, target_info: TargetInfo) -> u32 {
use Layout::*;
match self {
@ -1056,18 +1082,7 @@ impl<'a> Layout<'a> {
sum
}
Union(variant) => {
use UnionLayout::*;
match variant {
NonRecursive(_) => variant.data_size_and_alignment(target_info).0,
Recursive(_)
| NullableWrapped { .. }
| NullableUnwrapped { .. }
| NonNullableUnwrapped(_) => target_info.ptr_width() as u32,
}
}
Union(variant) => variant.stack_size_without_alignment(target_info),
LambdaSet(lambda_set) => lambda_set
.runtime_representation()
.stack_size_without_alignment(target_info),
@ -2950,4 +2965,16 @@ mod test {
assert_eq!(layout.stack_size(target_info), 1);
assert_eq!(layout.alignment_bytes(target_info), 1);
}
#[test]
fn memcpy_size_result_u32_unit() {
let ok_tag = &[Layout::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 target_info = TargetInfo::default_x86_64();
assert_eq!(layout.stack_size_without_alignment(target_info), 5);
}
}

View file

@ -265,7 +265,8 @@ pub fn helper<'a>(
let target = target_lexicon::Triple::host();
let opt_level = if cfg!(debug_assertions) {
OptLevel::Normal
// OptLevel::Normal
OptLevel::Optimize
} else {
OptLevel::Optimize
};