mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 11:52:19 +00:00
fix for when C has to return an empty tag union
This commit is contained in:
parent
b6bae82913
commit
edf557e480
2 changed files with 24 additions and 7 deletions
|
@ -3959,22 +3959,35 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx, 'env>(
|
|||
(RocReturn::ByPointer, CCReturn::Return) => {
|
||||
// Roc currently puts the return pointer at the end of the argument list.
|
||||
// As such, we drop the last element here instead of the first.
|
||||
(¶ms[..], ¶m_types[..param_types.len() - 1])
|
||||
(
|
||||
¶ms[..],
|
||||
¶m_types[..param_types.len().saturating_sub(1)],
|
||||
)
|
||||
}
|
||||
// Drop the return pointer the other way, if the C function returns by pointer but Roc
|
||||
// doesn't
|
||||
(RocReturn::Return, CCReturn::ByPointer) => (¶ms[1..], ¶m_types[..]),
|
||||
(RocReturn::ByPointer, CCReturn::ByPointer) => {
|
||||
// Both return by pointer but Roc puts it at the end and C puts it at the beginning
|
||||
(¶ms[1..], ¶m_types[..param_types.len() - 1])
|
||||
(
|
||||
¶ms[1..],
|
||||
¶m_types[..param_types.len().saturating_sub(1)],
|
||||
)
|
||||
}
|
||||
(RocReturn::Return | RocReturn::ByPointer, CCReturn::Void) => {
|
||||
// the roc function returns a unit value. like `{}` or `{ { {}, {} }, {} }`.
|
||||
// In C, this is modelled as a function returning void
|
||||
(
|
||||
¶ms[..],
|
||||
¶m_types[..param_types.len().saturating_sub(1)],
|
||||
)
|
||||
}
|
||||
_ => (¶ms[..], ¶m_types[..]),
|
||||
};
|
||||
|
||||
dbg!(¶ms, ¶m_types);
|
||||
|
||||
debug_assert!(
|
||||
params.len() == param_types.len(),
|
||||
debug_assert_eq!(
|
||||
params.len(),
|
||||
param_types.len(),
|
||||
"when exposing a function to the host, params.len() was {}, but param_types.len() was {}",
|
||||
params.len(),
|
||||
param_types.len()
|
||||
|
@ -5729,6 +5742,8 @@ impl<'ctx> FunctionSpec<'ctx> {
|
|||
(return_type.unwrap().fn_type(&arguments, false), None)
|
||||
}
|
||||
CCReturn::Void => {
|
||||
// NOTE: there may be a valid return type, but it is zero-sized.
|
||||
// for instance just `{}` or something more complex like `{ { {}, {} }, {} }`
|
||||
let arguments = function_arguments(env, argument_types);
|
||||
(env.context.void_type().fn_type(&arguments, false), None)
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ pub fn struct_type_from_union_layout<'a, 'ctx, 'env>(
|
|||
use UnionLayout::*;
|
||||
|
||||
match union_layout {
|
||||
NonRecursive([]) => env.context.struct_type(&[], false),
|
||||
NonRecursive(tags) => {
|
||||
RocUnion::tagged_from_slices(layout_interner, env.context, tags, env.target_info)
|
||||
.struct_type()
|
||||
|
@ -300,7 +301,8 @@ impl<'ctx> RocUnion<'ctx> {
|
|||
target_info: TargetInfo,
|
||||
) -> Self {
|
||||
let tag_type = match layouts.len() {
|
||||
0..=255 => TagType::I8,
|
||||
0 => unreachable!("zero-element tag union is not represented as a RocUnion"),
|
||||
1..=255 => TagType::I8,
|
||||
_ => TagType::I16,
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue