mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-24 20:42:29 +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) => {
|
(RocReturn::ByPointer, CCReturn::Return) => {
|
||||||
// Roc currently puts the return pointer at the end of the argument list.
|
// 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.
|
// 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
|
// Drop the return pointer the other way, if the C function returns by pointer but Roc
|
||||||
// doesn't
|
// doesn't
|
||||||
(RocReturn::Return, CCReturn::ByPointer) => (¶ms[1..], ¶m_types[..]),
|
(RocReturn::Return, CCReturn::ByPointer) => (¶ms[1..], ¶m_types[..]),
|
||||||
(RocReturn::ByPointer, CCReturn::ByPointer) => {
|
(RocReturn::ByPointer, CCReturn::ByPointer) => {
|
||||||
// Both return by pointer but Roc puts it at the end and C puts it at the beginning
|
// 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[..]),
|
_ => (¶ms[..], ¶m_types[..]),
|
||||||
};
|
};
|
||||||
|
|
||||||
dbg!(¶ms, ¶m_types);
|
debug_assert_eq!(
|
||||||
|
params.len(),
|
||||||
debug_assert!(
|
param_types.len(),
|
||||||
params.len() == param_types.len(),
|
|
||||||
"when exposing a function to the host, params.len() was {}, but param_types.len() was {}",
|
"when exposing a function to the host, params.len() was {}, but param_types.len() was {}",
|
||||||
params.len(),
|
params.len(),
|
||||||
param_types.len()
|
param_types.len()
|
||||||
|
@ -5729,6 +5742,8 @@ impl<'ctx> FunctionSpec<'ctx> {
|
||||||
(return_type.unwrap().fn_type(&arguments, false), None)
|
(return_type.unwrap().fn_type(&arguments, false), None)
|
||||||
}
|
}
|
||||||
CCReturn::Void => {
|
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);
|
let arguments = function_arguments(env, argument_types);
|
||||||
(env.context.void_type().fn_type(&arguments, false), None)
|
(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::*;
|
use UnionLayout::*;
|
||||||
|
|
||||||
match union_layout {
|
match union_layout {
|
||||||
|
NonRecursive([]) => env.context.struct_type(&[], false),
|
||||||
NonRecursive(tags) => {
|
NonRecursive(tags) => {
|
||||||
RocUnion::tagged_from_slices(layout_interner, env.context, tags, env.target_info)
|
RocUnion::tagged_from_slices(layout_interner, env.context, tags, env.target_info)
|
||||||
.struct_type()
|
.struct_type()
|
||||||
|
@ -300,7 +301,8 @@ impl<'ctx> RocUnion<'ctx> {
|
||||||
target_info: TargetInfo,
|
target_info: TargetInfo,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let tag_type = match layouts.len() {
|
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,
|
_ => TagType::I16,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue