mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-21 18:01:15 +00:00
[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:
parent
4f436e8245
commit
70af362562
3 changed files with 24 additions and 6 deletions
|
@ -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,
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue