[qfcc] Unify temp def, return value and parameter sizes

In working with vectors and matrices while testing the scene wrappers, I
found that there was a fair bit of confusion about how large something
could be. Return values can be up to 32 words (but qfcc wasn't aware of
that), parameters were limited to 4 words still (and possibly should be
for varargs), and temp defs were limited to 8 words (1 lvec4). Temps are
used for handling return values (at least when not optimizing) and thus
must be capable of holding a return value, and passing large arguments
through *formal* parameters should be allowed. It seems reasonable to
limit parameter sizes to return value sizes.

A temp and a move are still used for large return values (4x4 matrix),
but that's an optimization issue: the code itself is at least correct.
This commit is contained in:
Bill Currie 2022-02-15 08:39:20 +09:00
parent 4f436e8245
commit 70af362562
3 changed files with 24 additions and 6 deletions

View file

@ -41,7 +41,8 @@
#include "def.h"
#define MAX_DEF_SIZE ((int)PR_SIZEOF(lvec4))
// The maximum size of a temp def, return value, or parameter value
#define MAX_DEF_SIZE 32
/** Represent an overloading of a function.
@ -152,6 +153,7 @@ param_t *check_params (param_t *params);
enum storage_class_e;
struct defspace_s;
int value_too_large (struct type_s *val_type) __attribute__((const));
void make_function (struct symbol_s *sym, const char *nice_name,
struct defspace_s *space, enum storage_class_e storage);
struct symbol_s *function_symbol (struct symbol_s *sym,

View file

@ -2197,12 +2197,14 @@ build_function_call (expr_t *fexpr, const type_t *ftype, expr_t *params)
return e;
}
if (!type_size (t))
if (!type_size (t)) {
err = error (e, "type of formal parameter %d is incomplete",
i + 1);
if (type_size (t) > type_size (&type_param))
}
if (value_too_large (t)) {
err = error (e, "formal parameter %d is too large to be passed by"
" value", i + 1);
}
if (i < param_count) {
if (e->type == ex_nil)
convert_nil (e, t = ftype->t.func.param_types[i]);

View file

@ -459,6 +459,18 @@ find_function (expr_t *fexpr, expr_t *params)
return fexpr;
}
int
value_too_large (type_t *val_type)
{
if ((options.code.progsversion < PROG_VERSION
&& type_size (val_type) > type_size (&type_param))
|| (options.code.progsversion == PROG_VERSION
&& type_size (val_type) > MAX_DEF_SIZE)) {
return 1;
}
return 0;
}
static void
check_function (symbol_t *fsym)
{
@ -470,7 +482,7 @@ check_function (symbol_t *fsym)
error (0, "return type is an incomplete type");
fsym->type->t.func.type = &type_void;//FIXME better type?
}
if (type_size (fsym->type->t.func.type) > type_size (&type_param)) {
if (value_too_large (fsym->type->t.func.type)) {
error (0, "return value too large to be passed by value (%d)",
type_size (&type_param));
fsym->type->t.func.type = &type_void;//FIXME better type?
@ -480,12 +492,14 @@ check_function (symbol_t *fsym)
continue; // ellipsis marker
if (!p->type)
continue; // non-param selector
if (!type_size (p->type))
if (!type_size (p->type)) {
error (0, "parameter %d (%s) has incomplete type",
i + 1, p->name);
if (type_size (p->type) > type_size (&type_param))
}
if (value_too_large (p->type)) {
error (0, "param %d (%s) is too large to be passed by value",
i + 1, p->name);
}
}
}