From 55a5782a95e480aa2f99ee1e2f47b20ff3d87897 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 7 Sep 2024 02:36:54 +0900 Subject: [PATCH] [qfcc] Save the type evaluation code I don't yet know whether the generated code is correct, but the little functions that compute a generic type gets stored in the function's params/return type. --- tools/qfcc/include/function.h | 20 +++++++------- tools/qfcc/source/expr_type.c | 19 ++++++------- tools/qfcc/source/function.c | 52 +++++++++++++++++++++-------------- 3 files changed, 50 insertions(+), 41 deletions(-) diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index 7d2ed844a..b7de65841 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -44,13 +44,18 @@ // The maximum size of a temp def, return value, or parameter value #define MAX_DEF_SIZE 32 -typedef struct function_s function_t; +typedef enum param_qual_e { + pq_const, + pq_in, + pq_out, + pq_inout, +} param_qual_t; -typedef const type_t *(*gentype_compute_f) (); +typedef struct function_s function_t; +typedef struct typeeval_s typeeval_t; typedef struct gentype_s { const char *name; - gentype_compute_f compute; // earlier types have priority over later types. null if compute valid const type_t **valid_types; } gentype_t; @@ -58,7 +63,9 @@ typedef struct gentype_s { typedef struct genparam_s { const char *name; const type_t *fixed_type; + typeeval_t *compute; int gentype; // index into function's list of types + param_qual_t qual; } genparam_t; typedef struct genfunc_s { @@ -163,13 +170,6 @@ typedef struct metafunc_s { extern function_t *current_func; -typedef enum param_qual_e { - pq_const, - pq_in, - pq_out, - pq_inout, -} param_qual_t; - /** Representation of a function parameter. \note The first two fields match the first two fields of keywordarg_t in method.h diff --git a/tools/qfcc/source/expr_type.c b/tools/qfcc/source/expr_type.c index b364cbb53..609342d22 100644 --- a/tools/qfcc/source/expr_type.c +++ b/tools/qfcc/source/expr_type.c @@ -912,19 +912,18 @@ build_type_function (const expr_t *te, int num_types, gentype_t *types) } C (OP_NOP, nullptr, nullptr, nullptr); def_t *res = nullptr; + typeeval_t *func = nullptr; if (!Sys_setjmp (ctx->jmpbuf)) { res = compute_type (te, ctx); - } else { - res = compute_tmp (ctx); + C (OP_RETURN, res, nullptr, 0); + func = malloc (sizeof (typeeval_t)); + *func = (typeeval_t) { + .code = code->code, + .data = data->data, + .code_size = code->size, + .data_size = data->size, + }; } - C (OP_RETURN, res, nullptr, 0); - typeeval_t *func = malloc (sizeof (typeeval_t)); - *func = (typeeval_t) { - .code = code->code, - .data = data->data, - .code_size = code->size, - .data_size = data->size, - }; code->code = nullptr; data->data = nullptr; codespace_delete (code); diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index f4df5a965..3215c778e 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -111,6 +111,15 @@ check_generic_param (genparam_t *param, genfunc_t *genfunc) internal_error (0, "invalid type index %d on %s for %s", param->gentype, param->name, genfunc->name); } + if (param->compute) { + internal_error (0, "fixed and computed types on %s for %s", + param->name, genfunc->name); + } + } else if (param->compute) { + if (param->gentype != -1) { + internal_error (0, "invalid type index %d on %s for %s", + param->gentype, param->name, genfunc->name); + } } else if (param->gentype < 0 || param->gentype >= genfunc->num_types) { internal_error (0, "invalid type index %d on %s for %s", param->gentype, param->name, genfunc->name); @@ -126,10 +135,6 @@ cmp_genparams (genfunc_t *g1, genparam_t *p1, genfunc_t *g2, genparam_t *p2) // fixed_type for both p1 and p2 is null auto t1 = g1->types[p1->gentype]; auto t2 = g2->types[p2->gentype]; - if (t1.compute || t2.compute) { - // FIXME probably not right - return t1.compute == t2.compute; - } auto vt1 = t1.valid_types; auto vt2 = t2.valid_types; for (; *vt1 && *vt2 && *vt1 == *vt2; vt1++, vt2++) continue; @@ -143,9 +148,8 @@ add_generic_function (genfunc_t *genfunc) for (int i = 0; i < genfunc->num_types; i++) { auto gentype = &genfunc->types[i]; - if (gentype->compute && gentype->valid_types) { - internal_error (0, "both compute and valid_types set in " - "generic type"); + if (!gentype->valid_types) { + internal_error (0, "no valid_types set in generic type"); } for (auto type = gentype->valid_types; type && *type; type++) { if (is_void (*type)) { @@ -202,12 +206,6 @@ add_generic_function (genfunc_t *genfunc) } } -static gentype_compute_f -check_compute_type (const expr_t *expr) -{ - return nullptr; -} - static const type_t ** valid_type_list (const expr_t *expr) { @@ -242,13 +240,9 @@ make_gentype (const expr_t *expr) auto sym = expr->symbol; gentype_t gentype = { .name = save_string (sym->name), - .compute = check_compute_type (sym->expr), .valid_types = valid_type_list (sym->expr), }; - if (gentype.compute && gentype.valid_types) { - internal_error (expr, "both computed type and type list"); - } - if (!gentype.compute && !gentype.valid_types) { + if (!gentype.valid_types) { internal_error (expr, "empty generic type"); } return gentype; @@ -273,10 +267,18 @@ find_gentype (const expr_t *expr, genfunc_t *genfunc) static genparam_t make_genparam (param_t *param, genfunc_t *genfunc) { + int gentype = find_gentype (param->type_expr, genfunc); + typeeval_t *compute = nullptr; + if (gentype < 0 && param->type_expr) { + compute = build_type_function (param->type_expr, + genfunc->num_types, genfunc->types); + } genparam_t genparam = { .name = save_string (param->name), .fixed_type = param->type, - .gentype = find_gentype (param->type_expr, genfunc), + .compute = compute, + .gentype = gentype, + .qual = param->qual, }; return genparam; } @@ -302,7 +304,8 @@ parse_generic_function (const char *name, specifier_t spec) for (auto s = generic_tab->symbols; s; s = s->next) { bool found = false; for (auto q = &ret_param; q; q = q->next) { - // FIXME check complex expressions + // skip complex expressions because they will be either fixed + // or rely on earlier parameters if (!q->type_expr || q->type_expr->type != ex_symbol) { continue; } @@ -338,7 +341,7 @@ parse_generic_function (const char *name, specifier_t spec) num_gentype = 0; for (auto s = generic_tab->symbols; s; s = s->next) { for (auto q = &ret_param; q; q = q->next) { - // FIXME check complex expressions + // see complex expressions comment above if (!q->type_expr || q->type_expr->type != ex_symbol) { continue; } @@ -350,6 +353,7 @@ parse_generic_function (const char *name, specifier_t spec) } num_params = 0; + // skip return type so it can be done last to support complex expressions for (auto p = ret_param.next; p; p = p->next) { genfunc->params[num_params++] = make_genparam (p, genfunc); } @@ -754,6 +758,7 @@ find_generic_function (const expr_t *fexpr, genfunc_t **genfuncs, auto g = genfuncs[best_ind]; const type_t *types[g->num_types] = {}; const type_t *param_types[num_params]; + param_qual_t param_quals[num_params]; const type_t *return_type; for (int i = 0; i < num_params; i++) { auto p = &g->params[i]; @@ -766,6 +771,7 @@ find_generic_function (const expr_t *fexpr, genfunc_t **genfuncs, } else { param_types[i] = p->fixed_type; } + param_quals[i] = p->qual; } if (!g->ret_type->fixed_type) { int ind = g->ret_type->gentype; @@ -791,6 +797,7 @@ find_generic_function (const expr_t *fexpr, genfunc_t **genfuncs, .ret_type = return_type, .num_params = num_params, .param_types = param_types, + .param_quals = param_quals, }, }; auto type = find_type (&ftype); @@ -823,6 +830,7 @@ find_function (const expr_t *fexpr, const expr_t *params) int num_params = params ? list_count (¶ms->list) : 0; const type_t *arg_types[num_params + 1]; + param_qual_t arg_quals[num_params + 1]; const expr_t *args[num_params + 1]; if (params) { list_scatter_rev (¶ms->list, args); @@ -833,6 +841,7 @@ find_function (const expr_t *fexpr, const expr_t *params) return e; } arg_types[i] = get_type (e); + arg_quals[i] = pq_in; } type_t call_type = { @@ -840,6 +849,7 @@ find_function (const expr_t *fexpr, const expr_t *params) .func = { .num_params = num_params, .param_types = arg_types, + .param_quals = arg_quals, }, };