From 03967bd6238e13acdd91018fc1b27472d28eb39b Mon Sep 17 00:00:00 2001 From: ISSOtm Date: Sat, 21 Mar 2020 15:42:52 +0100 Subject: [PATCH] Prevent purging referenced symbols This is an immediate fix for #492, although #342 is needed to implement the desired functionality. --- include/asm/symbol.h | 1 + src/asm/symbol.c | 11 +++++++++++ test/asm/purge-ref.asm | 23 +++++++++++++++++++++++ test/asm/purge-ref.err | 7 +++++++ test/asm/purge-ref.out | 0 5 files changed, 42 insertions(+) create mode 100644 test/asm/purge-ref.asm create mode 100644 test/asm/purge-ref.err create mode 100644 test/asm/purge-ref.out diff --git a/include/asm/symbol.h b/include/asm/symbol.h index 2f96c20a..16a37ecb 100644 --- a/include/asm/symbol.h +++ b/include/asm/symbol.h @@ -33,6 +33,7 @@ struct sSymbol { bool isConstant; /* Whether the symbol's value is currently known */ bool isExported; /* Whether the symbol is to be exported */ bool isBuiltin; /* Whether the symbol is a built-in */ + bool isReferenced; /* Whether the symbol is referenced in a RPN expr */ struct sSymbol *pScope; struct sSymbol *pNext; struct Section *pSection; diff --git a/src/asm/symbol.c b/src/asm/symbol.c index 914464d8..79acb21c 100644 --- a/src/asm/symbol.c +++ b/src/asm/symbol.c @@ -127,6 +127,7 @@ static struct sSymbol *createsymbol(char const *s) (*ppsym)->isConstant = false; (*ppsym)->isExported = false; (*ppsym)->isBuiltin = false; + (*ppsym)->isReferenced = false; (*ppsym)->pScope = NULL; (*ppsym)->pNext = NULL; (*ppsym)->pSection = NULL; @@ -211,6 +212,11 @@ struct sSymbol *sym_FindSymbol(char const *tzName) return findsymbol(tzName, pscope); } +static inline bool isReferenced(struct sSymbol const *sym) +{ + return sym->isReferenced; +} + /* * Purge a symbol */ @@ -230,6 +236,9 @@ void sym_Purge(char const *tzName) yyerror("'%s' not defined", tzName); } else if ((*ppSym)->isBuiltin) { yyerror("Built-in symbol '%s' cannot be purged", tzName); + } else if (isReferenced(*ppSym)) { + yyerror("Symbol \"%s\" is referenced and thus cannot be purged", + tzName); } else { struct sSymbol *pSym; @@ -468,6 +477,7 @@ struct sSymbol *sym_AddReloc(char const *tzSym) else if (sym_IsDefined(nsym)) yyerror("'%s' already defined in %s(%d)", tzSym, nsym->tzFileName, nsym->nFileLine); + /* If the symbol already exists as a ref, just "take over" it */ nsym->nValue = nPC; nsym->type = SYM_LABEL; @@ -544,6 +554,7 @@ void sym_Ref(char const *tzSym) nsym = createsymbol(tzSym); nsym->type = SYM_REF; } + nsym->isReferenced = true; } /* diff --git a/test/asm/purge-ref.asm b/test/asm/purge-ref.asm new file mode 100644 index 00000000..348219af --- /dev/null +++ b/test/asm/purge-ref.asm @@ -0,0 +1,23 @@ +SECTION "test", ROM0 ; Important: do not purge this! + + dw ref + PURGE ref + +OK: + PURGE OK + + dw NotOK +NotOK: + PURGE NotOK + +EvenLessOK: + dw EvenLessOK + PURGE EvenLessOK + +SECTION "fixed", ROM0[0] + +Maybe: + dw Maybe + ; This is currently fine because the expression above is fully evaluated + ; above, so it's fine as of now... but changing it might make sense + PURGE Maybe diff --git a/test/asm/purge-ref.err b/test/asm/purge-ref.err new file mode 100644 index 00000000..d9974bcf --- /dev/null +++ b/test/asm/purge-ref.err @@ -0,0 +1,7 @@ +ERROR: purge-ref.asm(4): + Symbol "ref" is referenced and thus cannot be purged +ERROR: purge-ref.asm(11): + Symbol "NotOK" is referenced and thus cannot be purged +ERROR: purge-ref.asm(15): + Symbol "EvenLessOK" is referenced and thus cannot be purged +error: Assembly aborted (3 errors)! diff --git a/test/asm/purge-ref.out b/test/asm/purge-ref.out new file mode 100644 index 00000000..e69de29b