mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-04-07 18:01:30 +00:00
[qfcc] Add reference_expr()
to create references
`address_expr()` wasn't enough because it returns pointers instead of references (quite correct) which messes with checks for references elsewhere (also quite correct). It seems I've finally got reference parameters working.
This commit is contained in:
parent
9c3dc555a3
commit
5b9d241177
3 changed files with 56 additions and 34 deletions
|
@ -1094,6 +1094,7 @@ const expr_t *deref_pointer_expr (const expr_t *pointer);
|
|||
const expr_t *pointer_deref (const expr_t *pointer);
|
||||
const expr_t *offset_pointer_expr (const expr_t *pointer, const expr_t *offset);
|
||||
const expr_t *address_expr (const expr_t *e1, const type_t *t);
|
||||
const expr_t *reference_expr (const expr_t *e1, const type_t *t);
|
||||
const expr_t *build_if_statement (bool not, const expr_t *test,
|
||||
const expr_t *s1, const expr_t *els,
|
||||
const expr_t *s2);
|
||||
|
|
|
@ -2528,14 +2528,11 @@ offset_pointer_expr (const expr_t *pointer, const expr_t *offset)
|
|||
return cast_expr (ptr_type, ptr);
|
||||
}
|
||||
|
||||
const expr_t *
|
||||
address_expr (const expr_t *e1, const type_t *t)
|
||||
static expr_t *
|
||||
core_address_expr (const expr_t *e1, const type_t *t)
|
||||
{
|
||||
expr_t *e;
|
||||
|
||||
if (e1->type == ex_error)
|
||||
return e1;
|
||||
|
||||
if (!t)
|
||||
t = get_type (e1);
|
||||
|
||||
|
@ -2553,9 +2550,9 @@ address_expr (const expr_t *e1, const type_t *t)
|
|||
}
|
||||
if (is_array (type)) {
|
||||
auto ptrval = new_pointer_val (0, t, def, 0);
|
||||
return new_value_expr (ptrval, false);
|
||||
return (expr_t *) new_value_expr (ptrval, false);
|
||||
} else {
|
||||
return new_pointer_expr (0, t, def);
|
||||
return (expr_t *) new_pointer_expr (0, t, def);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2572,13 +2569,13 @@ address_expr (const expr_t *e1, const type_t *t)
|
|||
|
||||
if (is_array (type)) {
|
||||
auto ptrval = new_pointer_val (0, t, def, 0);
|
||||
return new_value_expr (ptrval, false);
|
||||
return (expr_t *) new_value_expr (ptrval, false);
|
||||
} else {
|
||||
return new_pointer_expr (0, t, def);
|
||||
return (expr_t *) new_pointer_expr (0, t, def);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return error (e1, "invalid type for unary &");
|
||||
return (expr_t *) error (e1, "invalid type for unary &");
|
||||
case ex_field:
|
||||
e = new_address_expr (e1->field.type, e1, nullptr);
|
||||
break;
|
||||
|
@ -2588,16 +2585,16 @@ address_expr (const expr_t *e1, const type_t *t)
|
|||
e1->expr.e1, e1->expr.e2);
|
||||
break;
|
||||
}
|
||||
return error (e1, "invalid type for unary &");
|
||||
return (expr_t *) error (e1, "invalid type for unary &");
|
||||
case ex_uexpr:
|
||||
if (e1->expr.op == '.') {
|
||||
auto p = e1->expr.e1;
|
||||
auto p = (expr_t *) e1->expr.e1;
|
||||
if (p->type == ex_expr && p->expr.op == '.') {
|
||||
p = new_address_expr (p->expr.type, p->expr.e1, p->expr.e2);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
return error (e1, "invalid type for unary &");
|
||||
return (expr_t *) error (e1, "invalid type for unary &");
|
||||
case ex_label:
|
||||
return new_label_ref (&e1->label);
|
||||
case ex_temp:
|
||||
|
@ -2609,11 +2606,40 @@ address_expr (const expr_t *e1, const type_t *t)
|
|||
}
|
||||
return new_address_expr (t, e1, 0);
|
||||
default:
|
||||
return error (e1, "invalid type for unary &");
|
||||
return (expr_t *) error (e1, "invalid type for unary &");
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
const expr_t *
|
||||
address_expr (const expr_t *e1, const type_t *t)
|
||||
{
|
||||
if (is_error (e1)) {
|
||||
return e1;
|
||||
}
|
||||
return core_address_expr (e1, t);
|
||||
}
|
||||
|
||||
const expr_t *
|
||||
reference_expr (const expr_t *e, const type_t *t)
|
||||
{
|
||||
if (is_error (e)) {
|
||||
return e;
|
||||
}
|
||||
auto ref = core_address_expr (e, t);
|
||||
if (is_error (ref)) {
|
||||
return ref;
|
||||
}
|
||||
if (ref->type != ex_address) {
|
||||
internal_error (ref, "expected address expression");
|
||||
}
|
||||
auto type = get_type (ref);
|
||||
type = dereference_type (type);
|
||||
type = reference_type (type);
|
||||
ref->address.type = type;
|
||||
return ref;
|
||||
}
|
||||
|
||||
const expr_t *
|
||||
build_if_statement (bool not, const expr_t *test, const expr_t *s1,
|
||||
const expr_t *els, const expr_t *s2)
|
||||
|
|
|
@ -205,6 +205,18 @@ check_arg_types (const expr_t **arguments, const type_t **arg_types,
|
|||
return err;
|
||||
}
|
||||
|
||||
static const expr_t *
|
||||
reference_param (const type_t *ptype, const expr_t *arg)
|
||||
{
|
||||
auto arg_type = get_type (arg);
|
||||
if (is_reference (ptype) && !is_reference (arg_type)) {
|
||||
arg = reference_expr (arg, nullptr);
|
||||
} else if (!is_reference (ptype) && is_reference (arg_type)) {
|
||||
arg = pointer_deref (arg);
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
static void
|
||||
build_call_scope (symbol_t *fsym, const expr_t **arguments)
|
||||
{
|
||||
|
@ -236,14 +248,7 @@ build_call_scope (symbol_t *fsym, const expr_t **arguments)
|
|||
}
|
||||
auto psym = new_symbol (p->name);
|
||||
psym->sy_type = sy_expr;
|
||||
auto arg_type = get_type (arguments[i]);
|
||||
if (is_reference (p->type) && !is_reference (arg_type)) {
|
||||
psym->expr = address_expr (arguments[i], nullptr);
|
||||
} else if (!is_reference (p->type) && is_reference (arg_type)) {
|
||||
psym->expr = pointer_deref (arguments[i]);
|
||||
} else {
|
||||
psym->expr = arguments[i];
|
||||
}
|
||||
psym->expr = reference_param (p->type, arguments[i]);
|
||||
symtab_addsymbol (params, psym);
|
||||
}
|
||||
}
|
||||
|
@ -280,23 +285,13 @@ build_intrinsic_call (const expr_t *expr, symbol_t *fsym, const type_t *ftype,
|
|||
current_symtab = func->locals;
|
||||
for (int i = 0; i < extra_count; i++) {
|
||||
extra_args[i] = expr_process (extra_args[i], ctx);
|
||||
if (is_reference (get_type (extra_args[i]))) {
|
||||
extra_args[i] = pointer_deref (extra_args[i]);
|
||||
}
|
||||
}
|
||||
current_symtab = scope;
|
||||
list_gather (&call->intrinsic.operands, extra_args, extra_count);
|
||||
} else {
|
||||
auto p = fsym->params;
|
||||
for (int i = 0; i < arg_count; i++, p = p->next) {
|
||||
auto arg_type = get_type (arguments[i]);
|
||||
if (is_reference (p->type) && !is_reference (arg_type)) {
|
||||
arguments[i] = address_expr (arguments[i], nullptr);
|
||||
} else if (!is_reference (p->type) && is_reference (arg_type)) {
|
||||
arguments[i] = pointer_deref (arguments[i]);
|
||||
} else {
|
||||
arguments[i] = arguments[i];
|
||||
}
|
||||
arguments[i] = reference_param (p->type, arguments[i]);
|
||||
}
|
||||
list_gather (&call->intrinsic.operands, arguments, arg_count);
|
||||
}
|
||||
|
@ -416,7 +411,7 @@ build_args (const expr_t *(*arg_exprs)[2], int *arg_expr_count,
|
|||
if (is_reference (get_type (e))) {
|
||||
// just copy the param, so no op
|
||||
} else {
|
||||
e = address_expr (e, nullptr);
|
||||
e = reference_expr (e, nullptr);
|
||||
}
|
||||
} else {
|
||||
if (is_reference (get_type (e))) {
|
||||
|
|
Loading…
Reference in a new issue