From a7639a685ee8e5444565ab1f969a9c917752ac61 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Wed, 2 Oct 2024 02:01:33 +0900 Subject: [PATCH] [qfcc] Add field and array expression types And implement enough AST processing to compile fstrianglest.vert Plenty of code-gen issues, though. --- tools/qfcc/include/expr.h | 16 ++++++++ tools/qfcc/include/expr_names.h | 2 + tools/qfcc/source/expr.c | 32 +++++++++++++++ tools/qfcc/source/expr_assign.c | 4 ++ tools/qfcc/source/expr_dag.c | 14 +++++++ tools/qfcc/source/expr_process.c | 68 +++++++++++++++++++++++++++++++- tools/qfcc/source/glsl-parse.y | 12 +++--- tools/qfcc/source/statements.c | 5 +++ 8 files changed, 146 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index 0eeec880d..7032a5e79 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -333,6 +333,18 @@ typedef struct { const expr_t *false_expr; } ex_cond_t; +typedef struct { + const expr_t *object; + const expr_t *member; + const type_t *type; +} ex_field_t; + +typedef struct { + const expr_t *base; + const expr_t *index; + const type_t *type; +} ex_array_t; + #define POINTER_VAL(p) (((p).def ? (p).def->offset : 0) + (p).val) typedef struct expr_s { @@ -378,6 +390,8 @@ typedef struct expr_s { ex_type_t typ; ///< type expression ex_incop_t incop; ///< incop expression ex_cond_t cond; ///< ?: conditional expression + ex_field_t field; ///< field reference expression + ex_array_t array; ///< array index expression }; } expr_t; @@ -889,6 +903,8 @@ expr_t *new_with_expr (int mode, int reg, const expr_t *val); expr_t *new_incop_expr (int op, const expr_t *e, bool postop); expr_t *new_cond_expr (const expr_t *test, const expr_t *true_expr, const expr_t *false_expr); +expr_t *new_field_expr (const expr_t *object, const expr_t *member); +expr_t *new_array_expr (const expr_t *base, const expr_t *index); /** Create an expression of the correct type that references the specified parameter slot. diff --git a/tools/qfcc/include/expr_names.h b/tools/qfcc/include/expr_names.h index 23492aa00..9dd31f061 100644 --- a/tools/qfcc/include/expr_names.h +++ b/tools/qfcc/include/expr_names.h @@ -71,6 +71,8 @@ EX_EXPR(list) ///< non-invasive list of expressions (::ex_list_t) EX_EXPR(type) ///< type expression for generics EX_EXPR(incop) ///< pre or post increment/decrement (::ex_incop_t) EX_EXPR(cond) ///< ?: conditional expression (::ex_cond_t) +EX_EXPR(field) ///< field reference expression (::ex_field_t) +EX_EXPR(array) ///< array index ex_field_t (::ex_array_t) #undef EX_EXPR diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index a731bef02..1205f0ec7 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -212,6 +212,10 @@ get_type (const expr_t *e) //FIXME true_expr and false_expr need to have the same type, //unless one is nil return get_type (e->cond.true_expr); + case ex_field: + return e->field.type; + case ex_array: + return e->array.type; case ex_count: internal_error (e, "invalid expression"); } @@ -1949,6 +1953,11 @@ has_function_call (const expr_t *e) return (has_function_call (e->cond.test) || has_function_call (e->cond.true_expr) || has_function_call (e->cond.false_expr)); + case ex_field: + return has_function_call (e->field.object); + case ex_array: + return (has_function_call (e->array.base) + || has_function_call (e->array.index)); case ex_count: break; } @@ -2505,6 +2514,29 @@ new_cond_expr (const expr_t *test, const expr_t *true_expr, return cond; } +expr_t * +new_field_expr (const expr_t *object, const expr_t *member) +{ + auto field = new_expr (); + field->type = ex_field; + field->field = (ex_field_t) { + .object = object, + .member = member, + }; + return field; +} + +expr_t * +new_array_expr (const expr_t *base, const expr_t *index) +{ + auto array = new_expr (); + array->type = ex_array; + array->array = (ex_array_t) { + .base = base, + .index = index, + }; + return array; +} const expr_t * incop_expr (int op, const expr_t *e, int postop) diff --git a/tools/qfcc/source/expr_assign.c b/tools/qfcc/source/expr_assign.c index 9e96525dd..10ef9e422 100644 --- a/tools/qfcc/source/expr_assign.c +++ b/tools/qfcc/source/expr_assign.c @@ -136,6 +136,10 @@ is_lvalue (const expr_t *expr) case ex_cond: return (is_lvalue (expr->cond.true_expr) && is_lvalue (expr->cond.false_expr)); + case ex_field: + return 1; + case ex_array: + return 1; case ex_count: internal_error (expr, "invalid expression"); } diff --git a/tools/qfcc/source/expr_dag.c b/tools/qfcc/source/expr_dag.c index b46b17583..e58e95567 100644 --- a/tools/qfcc/source/expr_dag.c +++ b/tools/qfcc/source/expr_dag.c @@ -189,6 +189,20 @@ edag_add_expr (const expr_t *expr) return e; } break; + case ex_field: + if (e->field.type == expr->field.type + && e->field.object == expr->field.object + && e->field.member == expr->field.member) { + return e; + } + break; + case ex_array: + if (e->array.type == expr->array.type + && e->array.base == expr->array.base + && e->array.index == expr->array.index) { + return e; + } + break; } } DARRAY_APPEND (&expr_dag, expr); diff --git a/tools/qfcc/source/expr_process.c b/tools/qfcc/source/expr_process.c index eb3e0b43d..62111d311 100644 --- a/tools/qfcc/source/expr_process.c +++ b/tools/qfcc/source/expr_process.c @@ -75,6 +75,28 @@ proc_symbol (const expr_t *expr) return expr; } +static void +proc_do_list (ex_list_t *out, const ex_list_t *in) +{ + int count = list_count (in); + const expr_t *exprs[count + 1]; + list_scatter (in, exprs); + for (int i = 0; i < count; i++) { + exprs[i] = expr_process (exprs[i]); + } + list_gather (out, exprs, count); +} + +static const expr_t * +proc_vector (const expr_t *expr) +{ + auto vec = new_expr (); + vec->type = ex_vector; + vec->vector.type = expr->vector.type; + proc_do_list (&vec->vector.list, &expr->vector.list); + return vec; +} + static const expr_t * proc_value (const expr_t *expr) { @@ -92,15 +114,59 @@ proc_compound (const expr_t *expr) return comp; } +static const expr_t * +proc_assign (const expr_t *expr) +{ + auto dst = expr_process (expr->assign.dst); + auto src = expr_process (expr->assign.src); + if (is_error (src)) { + return src; + } + if (is_error (src)) { + return src; + } + return assign_expr (dst, src); +} + +static const expr_t * +proc_branch (const expr_t *expr) +{ + if (expr->branch.type == pr_branch_call) { + auto args = new_list_expr (nullptr); + proc_do_list (&args->list, &expr->branch.args->list); + return function_expr (expr->branch.target, args); + } else { + auto branch = new_expr (); + branch->type = ex_branch; + branch->branch = expr->branch; + branch->branch.target = expr_process (expr->branch.target); + branch->branch.index = expr_process (expr->branch.index); + branch->branch.test = expr_process (expr->branch.test); + if (is_error (branch->branch.target)) { + return branch->branch.target; + } + if (is_error (branch->branch.index)) { + return branch->branch.index; + } + if (is_error (branch->branch.test)) { + return branch->branch.test; + } + return branch; + } +} + const expr_t * expr_process (const expr_t *expr) { static process_f funcs[ex_count] = { [ex_expr] = proc_expr, [ex_uexpr] = proc_uexpr, + [ex_symbol] = proc_symbol, + [ex_vector] = proc_vector, [ex_value] = proc_value, [ex_compound] = proc_compound, - [ex_symbol] = proc_symbol, + [ex_assign] = proc_assign, + [ex_branch] = proc_branch, }; if (expr->type >= ex_count) { diff --git a/tools/qfcc/source/glsl-parse.y b/tools/qfcc/source/glsl-parse.y index fedffde28..b57b4f9a1 100644 --- a/tools/qfcc/source/glsl-parse.y +++ b/tools/qfcc/source/glsl-parse.y @@ -323,15 +323,15 @@ postfix_expression : primary_exprsssion | postfix_expression '[' integer_expression ']' { - $$ = array_expr ($1, $3); + $$ = new_array_expr ($1, $3); } | function_call | postfix_expression '.' IDENTIFIER/*FIELD_SELECTION*/ { auto sym = new_symbol_expr ($3); - $$ = field_expr ($1, sym); + $$ = new_field_expr ($1, sym); } - | postfix_expression INCOP { $$ = incop_expr ($2, $1, 1); } + | postfix_expression INCOP { $$ = new_incop_expr ($2, $1, 1); } ; integer_expression @@ -354,7 +354,7 @@ function_call_or_method auto func = exprs[count - 1]; auto args = new_list_expr (nullptr); list_gather (&args->list, exprs, count - 1); - $$ = function_expr (func, args); + $$ = call_expr (func, args, nullptr); } ; @@ -402,7 +402,7 @@ function_identifier unary_expression : postfix_expression - | INCOP unary_expression { $$ = incop_expr ($1, $2, 0); } + | INCOP unary_expression { $$ = new_incop_expr ($1, $2, 0); } | unary_operator unary_expression { $$ = new_unary_expr ($1, $2); } ; @@ -1041,7 +1041,7 @@ statement simple_statement : declaration_statement - | expression_statement + | expression_statement { $$ = expr_process ($1); }//FIXME shouldn't be here | selection_statement | switch_statement | case_label diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index d8cfe2068..e6ffae7bc 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -2078,6 +2078,11 @@ expr_symbol (sblock_t *sblock, const expr_t *e, operand_t **op) make_function (sym, 0, pr.symtab->space, sc_extern); } *op = def_operand (sym->metafunc->func->def, 0, e); + } else if (sym->sy_type == sy_convert) { + e = sym->convert.conv (sym, sym->convert.data); + return statement_subexpr (sblock, e, op); + } else if (sym->sy_type == sy_expr) { + return statement_subexpr (sblock, sym->expr, op); } else { internal_error (e, "unexpected symbol type: %s for %s", symtype_str (sym->sy_type), sym->name);