From cf756eb1a08b51ff89e5edab191cf9aa040efb40 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 8 Feb 2024 13:41:32 +0900 Subject: [PATCH] [qfcc] Emit statements for expressions only once The switch to using expression dags instead of trees meant that the statement generator could traverse sub-expressions multiple times. This is inefficient but usually ok if there are no side effects. However, side effects and branches (usually from ?:, due to labels) break: side effects happen more than once, and labels get emitted multiple times resulting in orphaned statement blocks (and, in the end, uninitialized temporaries). --- tools/qfcc/include/expr.h | 1 + tools/qfcc/source/statements.c | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index dee210ee3..236669a22 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -311,6 +311,7 @@ typedef struct { typedef struct expr_s { expr_t *next; + struct operand_s *op; expr_type type; ///< the type of the result of this expression int line; ///< source line that generated this expression pr_string_t file; ///< source file that generated this expression diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index ef07cef8c..b48564ab4 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -2046,7 +2046,13 @@ statement_subexpr (sblock_t *sblock, const expr_t *e, operand_t **op) internal_error (e, "unexpected sub-expression type: %s", expr_names[e->type]); - sblock = sfuncs[e->type] (sblock, e, op); + if (e->op) { + *op = e->op; + } else { + sblock = sfuncs[e->type] (sblock, e, op); + //FIXME const cast (store elsewhere) + ((expr_t *) e)->op = *op; + } return sblock; }