make wasm test harness work with by-pointer values being returned

This commit is contained in:
Folkert 2022-07-14 20:25:29 +02:00
parent 291b77c83b
commit ba7ffab790
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C

View file

@ -841,16 +841,20 @@ fn promote_to_wasm_test_wrapper<'a, 'ctx, 'env>(
&Layout::UNIT,
);
let (roc_return, output_type) = match roc_main_fn.get_type().get_return_type() {
Some(return_type) => {
let output_type = return_type.ptr_type(AddressSpace::Generic);
(RocReturn::Return, output_type.into())
}
None => {
assert_eq!(roc_main_fn.get_type().get_param_types().len(), 1);
let output_type = roc_main_fn.get_type().get_param_types()[0];
(RocReturn::ByPointer, output_type)
}
};
let main_fn = {
let c_function_spec = {
match roc_main_fn.get_type().get_return_type() {
Some(return_type) => {
let output_type = return_type.ptr_type(AddressSpace::Generic);
FunctionSpec::cconv(env, CCReturn::Return, Some(output_type.into()), &[])
}
None => todo!(),
}
};
let c_function_spec = FunctionSpec::cconv(env, CCReturn::Return, Some(output_type), &[]);
let c_function = add_func(
env.context,
@ -870,42 +874,43 @@ fn promote_to_wasm_test_wrapper<'a, 'ctx, 'env>(
let entry = context.append_basic_block(c_function, "entry");
builder.position_at_end(entry);
// call the main roc function
let roc_main_fn_result = call_roc_function(env, roc_main_fn, &top_level.result, &[]);
// reserve space for the result on the heap
// pub unsafe extern "C" fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void {
let (size, alignment) = top_level.result.stack_size_and_alignment(env.target_info);
let roc_alloc = env.module.get_function("roc_alloc").unwrap();
let call = builder.build_call(
roc_alloc,
&[
env.ptr_int().const_int(size as _, false).into(),
env.context
.i32_type()
.const_int(alignment as _, false)
.into(),
],
"result_ptr",
);
let roc_main_fn_result = call_roc_function(env, roc_main_fn, &top_level.result, &[]);
call.set_call_convention(C_CALL_CONV);
let void_ptr = call.try_as_basic_value().left().unwrap();
match roc_return {
RocReturn::Return => {
let call = builder.build_call(
roc_alloc,
&[
env.ptr_int().const_int(size as _, false).into(),
env.context
.i32_type()
.const_int(alignment as _, false)
.into(),
],
"result_ptr",
);
let ptr = builder.build_pointer_cast(
void_ptr.into_pointer_value(),
c_function
.get_type()
.get_return_type()
.unwrap()
.into_pointer_type(),
"cast_ptr",
);
call.set_call_convention(C_CALL_CONV);
let void_ptr = call.try_as_basic_value().left().unwrap();
builder.build_store(ptr, roc_main_fn_result);
builder.build_return(Some(&ptr));
let ptr = builder.build_pointer_cast(
void_ptr.into_pointer_value(),
output_type.into_pointer_type(),
"cast_ptr",
);
builder.build_store(ptr, roc_main_fn_result);
builder.build_return(Some(&ptr));
}
RocReturn::ByPointer => {
assert!(roc_main_fn_result.is_pointer_value());
builder.build_return(Some(&roc_main_fn_result));
}
}
c_function
};
@ -984,7 +989,7 @@ pub fn build_exp_literal<'a, 'ctx, 'env>(
if str_literal.len() < env.small_str_bytes() as usize {
match env.small_str_bytes() {
24 => small_str_ptr_width_8(env, parent, str_literal).into(),
12 => small_str_ptr_width_4(env, str_literal).into(),
12 => small_str_ptr_width_4(env, str_literal).into(),
_ => unreachable!("incorrect small_str_bytes"),
}
} else {
@ -1073,7 +1078,11 @@ fn small_str_ptr_width_4<'a, 'ctx, 'env>(
let ptr_type = env.context.i8_type().ptr_type(address_space);
let ptr = env.builder.build_int_to_ptr(ptr, ptr_type, "to_u8_ptr");
struct_from_fields(env, zig_str_type(env), [(0, ptr.into()), (1, len.into()), (2, cap.into())].into_iter())
struct_from_fields(
env,
zig_str_type(env),
[(0, ptr.into()), (1, len.into()), (2, cap.into())].into_iter(),
)
}
pub fn build_exp_call<'a, 'ctx, 'env>(