aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-09-12 00:18:11 +0200
committerEugen Wissner <belka@caraus.de>2026-09-12 00:18:11 +0200
commiteb1d068beeaaa420b558595751295eec35ad0c3c (patch)
treea10aadd88ba358726573f7324ff6f9c489ebad77 /gcc
parentbd2b80d6ac582b9f0bcd96c86d4b79bfdb64eca1 (diff)
downloadelna-eb1d068beeaaa420b558595751295eec35ad0c3c.tar.gz
Support variadic extern procedures
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gcc/elna-builtins.cc8
-rw-r--r--gcc/gcc/elna-generic.cc25
2 files changed, 27 insertions, 6 deletions
diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc
index 2dc1147..a8e54c8 100644
--- a/gcc/gcc/elna-builtins.cc
+++ b/gcc/gcc/elna-builtins.cc
@@ -59,7 +59,8 @@ namespace elna::gcc
.size = static_cast<std::size_t>(
(TYPE_PRECISION(elna_bool_type_node) + BITS_PER_UNIT - 1) / BITS_PER_UNIT),
.alignment = TYPE_ALIGN_UNIT(elna_bool_type_node)
- }
+ },
+ .c_int_properties = get_host_numeric_properties(integer_type_node)
};
return info;
}
@@ -176,6 +177,11 @@ namespace elna::gcc
{
return_type = get_inner_alias(procedure.return_type.proper_type, symbols);
}
+ if (procedure.variadic)
+ {
+ return build_varargs_function_type_array(return_type,
+ static_cast<int>(procedure.parameters.size()), parameter_types.data());
+ }
return build_function_type_array(return_type,
static_cast<int>(procedure.parameters.size()), parameter_types.data());
}
diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc
index 8ab6762..8fd2ec8 100644
--- a/gcc/gcc/elna-generic.cc
+++ b/gcc/gcc/elna-generic.cc
@@ -43,16 +43,29 @@ namespace elna::gcc
}
void generic_visitor::build_procedure_call(location_t call_location,
- tree procedure_address, const std::vector<boot::expression *>& arguments)
+ tree procedure_address, const std::vector<boot::expression *>& arguments,
+ const std::vector<boot::type>& variadic_types)
{
vec<tree, va_gc> *argument_trees = nullptr;
tree symbol_type = TREE_TYPE(TREE_TYPE(procedure_address));
+ const std::size_t fixed_count = arguments.size() - variadic_types.size();
vec_alloc(argument_trees, arguments.size());
- for (boot::expression *const argument : arguments)
+ for (std::size_t i = 0; i < arguments.size(); ++i)
{
- argument->accept(this);
+ arguments.at(i)->accept(this);
this->current_expression = prepare_rvalue(this->current_expression);
+
+ if (i >= fixed_count)
+ {
+ tree passed_type = get_inner_alias(variadic_types.at(i - fixed_count), this->symbols);
+
+ if (passed_type != TREE_TYPE(this->current_expression)
+ && (INTEGRAL_TYPE_P(passed_type) || SCALAR_FLOAT_TYPE_P(passed_type)))
+ {
+ this->current_expression = fold_convert(passed_type, this->current_expression);
+ }
+ }
argument_trees->quick_push(this->current_expression);
}
this->current_expression = fold_build_call_array_loc(call_location, TREE_TYPE(symbol_type),
@@ -114,11 +127,13 @@ namespace elna::gcc
{
this->current_expression = build1(ADDR_EXPR,
build_pointer_type(expression_type), this->current_expression);
- build_procedure_call(call_location, this->current_expression, call->arguments);
+ build_procedure_call(call_location, this->current_expression,
+ call->arguments, call->variadic_types);
}
else if (POINTER_TYPE_P(expression_type) && TREE_CODE(TREE_TYPE(expression_type)) == FUNCTION_TYPE)
{
- build_procedure_call(call_location, this->current_expression, call->arguments);
+ build_procedure_call(call_location, this->current_expression,
+ call->arguments, call->variadic_types);
}
else
{