From 5b9d241177b675834e184ce16a733a2541050147 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 22 Jan 2025 14:59:03 +0900 Subject: [PATCH] [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. --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/expr.c | 54 ++++++++++++++++++++++++++--------- tools/qfcc/source/expr_call.c | 35 ++++++++++------------- 3 files changed, 56 insertions(+), 34 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index dd29630a5..58bdffcc9 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -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); diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index f4fe472de..f23dee132 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -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) diff --git a/tools/qfcc/source/expr_call.c b/tools/qfcc/source/expr_call.c index 3589b263e..589cfee53 100644 --- a/tools/qfcc/source/expr_call.c +++ b/tools/qfcc/source/expr_call.c @@ -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))) {