From c8308c46f201842cb9067212c0f0e234d9fd1bcb Mon Sep 17 00:00:00 2001 From: Blub Date: Tue, 22 Dec 2009 21:38:52 +0000 Subject: [PATCH] Patch by div0: add temp locking to ADDSTOREP emulation This avoids the issue that temps used in += operations can be overwritten by function calls in the expression. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3483 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/qclib/qcc_pr_comp.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index cb7abd285..fa2fcf59e 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -1381,7 +1381,12 @@ static void QCC_LockActiveTemps(void) t->scope = pr_scope; t = t->next; } - +} + +static void QCC_LockTemp(QCC_def_t *d) +{ + if (d->temp && d->temp->used) + d->temp->scope = pr_scope; } static void QCC_RemapLockedTemp(temp_t *t, int firststatement, int laststatement) @@ -2234,19 +2239,26 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var //don't chain these... this expansion is not the same. { int st; - + int need_lock = false; for (st = numstatements-2; st>=0; st--) { if (statements[st].op == OP_ADDRESS) if (statements[st].c == var_b->ofs) break; + if (statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8 || statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H) + need_lock = true; + + //printf("%s\n", pr_opcodes[statements[st].op].opname); + if (statements[st].c == var_b->ofs) QCC_PR_ParseWarning(0, "Temp-reuse may have broken your %s", op->name); } if (st < 0) QCC_PR_ParseError(ERR_INTERNAL, "XSTOREP_F: pointer was not generated from previous statement"); var_c = QCC_GetTemp(*op->type_c); + if(need_lock) + QCC_LockTemp(var_c); // this will cause the temp to be remapped by QCC_RemapLockedTemps statement_linenums[statement-statements] = statement_linenums[st]; statement->op = OP_ADDRESS; @@ -2351,6 +2363,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var op = &pr_opcodes[OP_STOREP_F]; QCC_FreeTemp(var_c); + var_c = NULL; QCC_FreeTemp(var_b); @@ -2367,18 +2380,24 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var //don't chain these... this expansion is not the same. { int st; + int need_lock = false; for (st = numstatements-2; st>=0; st--) { if (statements[st].op == OP_ADDRESS) if (statements[st].c == var_b->ofs) break; + if (statements[st].op >= OP_CALL0 && statements[st].op <= OP_CALL8 || statements[st].op >= OP_CALL1H && statements[st].op <= OP_CALL8H) + need_lock = true; + if (statements[st].c == var_b->ofs) QCC_PR_ParseWarning(0, "Temp-reuse may have broken your %s", op->name); } if (st < 0) QCC_PR_ParseError(ERR_INTERNAL, "XSTOREP_V couldn't find pointer generation"); var_c = QCC_GetTemp(*op->type_c); + if(need_lock) + QCC_LockTemp(var_c); // this will cause the temp to be remapped by QCC_RemapLockedTemps statement_linenums[statement-statements] = statement_linenums[st]; statement->op = OP_ADDRESS;