diff --git a/tools/qfcc/include/evaluate_type.h b/tools/qfcc/include/evaluate_type.h index cdf51fb94..8fa2c373a 100644 --- a/tools/qfcc/include/evaluate_type.h +++ b/tools/qfcc/include/evaluate_type.h @@ -70,10 +70,13 @@ void setup_type_progs (void); typedef struct expr_s expr_t; typedef struct gentype_s gentype_t; +typedef struct rua_ctx_s rua_ctx_t; + typeeval_t *build_type_function (const expr_t *te, int num_types, gentype_t *types); const type_t *evaluate_type (const typeeval_t *typeeval, int num_types, - const type_t **types, const expr_t *expr); + const type_t **types, const expr_t *expr, + rua_ctx_t *rua_ctx); ///@} #endif//__evaluate_type_h diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 5f146de82..39af97921 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -1075,7 +1075,8 @@ const expr_t *asx_expr (int op, const expr_t *e1, const expr_t *e2); const expr_t *unary_expr (int op, const expr_t *e); const expr_t *build_function_call (const expr_t *fexpr, const type_t *ftype, const expr_t *params); -const expr_t *function_expr (const expr_t *e1, const expr_t *e2); +const expr_t *function_expr (const expr_t *e1, const expr_t *e2, + rua_ctx_t *ctx); const expr_t *get_column (const expr_t *e, int i); const expr_t *constructor_expr (const expr_t *e, const expr_t *params); struct function_s; diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index f63640912..04f6e31b1 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -218,7 +218,8 @@ function_t *make_function (symbol_t *sym, const char *nice_name, struct defspace_s *space, enum storage_class_e storage); symbol_t *function_symbol (specifier_t spec, rua_ctx_t *ctx); -const expr_t *find_function (const expr_t *fexpr, const expr_t *params); +const expr_t *find_function (const expr_t *fexpr, const expr_t *params, + rua_ctx_t *ctx); function_t *begin_function (specifier_t spec, const char *nicename, symtab_t *parent, rua_ctx_t *ctx); void build_code_function (specifier_t spec, const expr_t *state_expr, diff --git a/tools/qfcc/source/evaluate.c b/tools/qfcc/source/evaluate.c index a28ca699d..97ee619c5 100644 --- a/tools/qfcc/source/evaluate.c +++ b/tools/qfcc/source/evaluate.c @@ -67,13 +67,14 @@ evaluate_debug_handler (prdebug_t event, void *param, void *data) case prd_breakpoint: case prd_subenter: case prd_subexit: - case prd_runerror: case prd_watchpoint: case prd_begin: case prd_terminate: case prd_error: case prd_none: break; + case prd_runerror: + internal_error (0, "program error in evaluation"); } } diff --git a/tools/qfcc/source/evaluate_type.c b/tools/qfcc/source/evaluate_type.c index 03be65bf0..de157dd09 100644 --- a/tools/qfcc/source/evaluate_type.c +++ b/tools/qfcc/source/evaluate_type.c @@ -36,6 +36,7 @@ #include "QF/simd/types.h" +#include "tools/qfcc/include/attribute.h" #include "tools/qfcc/include/codespace.h" #include "tools/qfcc/include/def.h" #include "tools/qfcc/include/defspace.h" @@ -57,6 +58,7 @@ typedef struct typectx_s { const type_t **types; int num_types; const expr_t *expr; + rua_ctx_t *rua_ctx; sys_jmpbuf jmpbuf; } typectx_t; @@ -73,6 +75,37 @@ fetch_type (unsigned id, typectx_t *ctx) return type; } +static void +tf_attribute_func (progs_t *pr, void *data) +{ + auto ctx = *(typectx_t **) data; + unsigned id = P_UINT (pr, 0); + auto type = fetch_type (id, ctx); + if (!type->attrib) { + error (ctx->expr, "type doesn't support attributes"); + Sys_longjmp (ctx->jmpbuf); + } + auto attr_params = &P_STRUCT (pr, pr_int_t, 1); + auto name = PR_GetString (pr, attr_params[0]); + int count = attr_params[1]; + attribute_t *attrib = nullptr; + if (count) { + const expr_t *param_exprs[count] = {}; + internal_error (ctx->expr, "not implemented"); + auto params = new_list_expr (nullptr); + list_gather (¶ms->list, param_exprs, count); + attrib = new_attribute (name, params); + } else { + attrib = new_attribute (name, nullptr); + } + auto e = type->attrib (type, attrib); + if (is_error (e)) { + Sys_longjmp (ctx->jmpbuf); + } + type = resolve_type (e, ctx->rua_ctx); + R_UINT (pr) = type->id; +} + static void tf_function_func (progs_t *pr, void *data) { @@ -239,6 +272,7 @@ static typectx_t *type_genfunc; static bfunction_t type_functions[] = { {}, // null function [tf_eval] = { .first_statement = 1 }, + TF_FUNC(tf_attribute), TF_FUNC(tf_function), TF_FUNC(tf_field), TF_FUNC(tf_pointer), @@ -302,12 +336,13 @@ setup_type_progs (void) const type_t * evaluate_type (const typeeval_t *typeeval, int num_types, const type_t **types, - const expr_t *expr) + const expr_t *expr, rua_ctx_t *rua_ctx) { typectx_t ctx = { - types = types, - num_types = num_types, - expr = expr, + .types = types, + .num_types = num_types, + .expr = expr, + .rua_ctx = rua_ctx, }; int err; if ((err = Sys_setjmp (ctx.jmpbuf))) { @@ -317,6 +352,8 @@ evaluate_type (const typeeval_t *typeeval, int num_types, const type_t **types, type_pr.pr_statements = typeeval->code; type_pr.pr_globals = typeeval->data; type_pr.globals_size = typeeval->data_size; + type_pr.pr_strings = (char *) typeeval->strings; + type_pr.pr_stringsize = typeeval->string_size; type_pr.pr_trace = options.verbosity > 1; PR_ExecuteProgram (&type_pr, tf_eval); unsigned id = R_UINT (&type_pr); diff --git a/tools/qfcc/source/expr_call.c b/tools/qfcc/source/expr_call.c index 39f1a9d3f..48c118e2f 100644 --- a/tools/qfcc/source/expr_call.c +++ b/tools/qfcc/source/expr_call.c @@ -447,13 +447,13 @@ build_function_call (const expr_t *fexpr, const type_t *ftype, } const expr_t * -function_expr (const expr_t *fexpr, const expr_t *args) +function_expr (const expr_t *fexpr, const expr_t *args, rua_ctx_t *ctx) { if (fexpr->type == ex_type) { return constructor_expr (fexpr, args); } - fexpr = find_function (fexpr, args); + fexpr = find_function (fexpr, args, ctx); if (is_error (fexpr)) { return fexpr; } diff --git a/tools/qfcc/source/expr_process.c b/tools/qfcc/source/expr_process.c index b41e53126..3d7985843 100644 --- a/tools/qfcc/source/expr_process.c +++ b/tools/qfcc/source/expr_process.c @@ -509,7 +509,7 @@ proc_branch (const expr_t *expr, rua_ctx_t *ctx) return new_error_expr (); } } - return function_expr (target, args); + return function_expr (target, args, ctx); } else { auto branch = new_expr (); branch->type = ex_branch; diff --git a/tools/qfcc/source/expr_type.c b/tools/qfcc/source/expr_type.c index 1075751d1..6cf65a8c5 100644 --- a/tools/qfcc/source/expr_type.c +++ b/tools/qfcc/source/expr_type.c @@ -529,7 +529,7 @@ compute_attribute (int arg_count, const expr_t **args, comp_ctx_t *ctx) } } C (OP_STORE_A_1, ctx->args[0], nullptr, type); - C (OP_STORE_A_1, ctx->args[1], nullptr, attr_params); + C (OP_LEA_A, attr_params, nullptr, ctx->args[1]); C (OP_CALL_B, ctx->funcs[tf_attribute], nullptr, res); return res; } diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index 67945fcce..d627b817a 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -666,7 +666,7 @@ select_type (gentype_t *gentype, callparm_t param) static genfunc_t * find_generic_function (genfunc_t **genfuncs, const expr_t *fexpr, - calltype_t *calltype, bool promote) + calltype_t *calltype, bool promote, rua_ctx_t *ctx) { int num_funcs = 0; for (auto gf = genfuncs; *gf; gf++, num_funcs++) continue; @@ -683,7 +683,11 @@ find_generic_function (genfunc_t **genfuncs, const expr_t *fexpr, bool ok = true; for (int i = 0; ok && i < num_params; i++) { auto p = &g->params[i]; - if (!p->fixed_type) { + if (p->compute) { + auto ptype = evaluate_type (p->compute, g->num_types, + types, fexpr, ctx); + ok &= check_type (ptype, call_params[i], costs + j, promote); + } else if (!p->fixed_type) { costs[j] += 1; int ind = p->gentype; if (!types[ind]) { @@ -727,7 +731,7 @@ find_generic_function (genfunc_t **genfuncs, const expr_t *fexpr, static const type_t * compute_param_type (const genparam_t *param, int param_ind, const genfunc_t *genfunc, calltype_t *calltype, - const expr_t *fexpr) + const expr_t *fexpr, rua_ctx_t *ctx) { auto call_types = calltype->types; auto call_params = calltype->params; @@ -736,7 +740,7 @@ compute_param_type (const genparam_t *param, int param_ind, } if (param->compute) { return evaluate_type (param->compute, genfunc->num_types, - calltype->types, fexpr); + calltype->types, fexpr, ctx); } int ind = param->gentype; if (!call_types[ind] && param_ind >= 0) { @@ -747,7 +751,8 @@ compute_param_type (const genparam_t *param, int param_ind, } static symbol_t * -create_generic_sym (genfunc_t *g, const expr_t *fexpr, calltype_t *calltype) +create_generic_sym (genfunc_t *g, const expr_t *fexpr, calltype_t *calltype, + rua_ctx_t *ctx) { int num_params = calltype->num_params; const type_t *param_types[num_params]; @@ -755,10 +760,10 @@ create_generic_sym (genfunc_t *g, const expr_t *fexpr, calltype_t *calltype) const type_t *return_type; for (int i = 0; i < num_params; i++) { auto p = &g->params[i]; - param_types[i] = compute_param_type (p, i, g, calltype, fexpr); + param_types[i] = compute_param_type (p, i, g, calltype, fexpr, ctx); param_quals[i] = p->qual; } - return_type = compute_param_type (g->ret_type, -1, g, calltype, fexpr); + return_type = compute_param_type (g->ret_type, -1, g, calltype, fexpr, ctx); if (!return_type) { internal_error (0, "return type not determined"); } @@ -837,11 +842,12 @@ get_function (const char *name, specifier_t spec, rua_ctx_t *ctx) || !fexpr.symbol->metafunc) { internal_error (0, "genfunc oops"); } - auto gen = find_generic_function (genfuncs, &fexpr, &calltype, false); + auto gen = find_generic_function (genfuncs, &fexpr, &calltype, false, + ctx); if (gen) { const type_t *ref_types[gen->num_types] = {}; calltype.types = ref_types; - auto sym = create_generic_sym (gen, &fexpr, &calltype); + auto sym = create_generic_sym (gen, &fexpr, &calltype, ctx); if (sym == fexpr.symbol || sym->metafunc == fexpr.symbol->metafunc) { internal_error (0, "genfunc oops"); @@ -1013,7 +1019,7 @@ new_function (const char *name, const char *nice_name) } const expr_t * -find_function (const expr_t *fexpr, const expr_t *params) +find_function (const expr_t *fexpr, const expr_t *params, rua_ctx_t *ctx) { if (fexpr->type != ex_symbol) { return fexpr; @@ -1045,13 +1051,14 @@ find_function (const expr_t *fexpr, const expr_t *params) const char *fname = fsym->name; auto genfuncs = (genfunc_t **) Hash_FindList (generic_functions, fname); if (genfuncs) { - auto gen = find_generic_function (genfuncs, fexpr, &calltype, true); + auto gen = find_generic_function (genfuncs, fexpr, &calltype, true, + ctx); if (!gen) { return new_error_expr (); } const type_t *ref_types[gen->num_types] = {}; calltype.types = ref_types; - auto sym = create_generic_sym (gen, fexpr, &calltype); + auto sym = create_generic_sym (gen, fexpr, &calltype, ctx); if (gen->can_inline) { // the call will be inlined, so a new scope is needed every // time