shithub: rgbds

Download patch

ref: 03967bd6238e13acdd91018fc1b27472d28eb39b
parent: eb445271df55b5fc3a45b238f6944c5528158b5a
author: ISSOtm <eldredhabert0@gmail.com>
date: Sat Mar 21 11:42:52 EDT 2020

Prevent purging referenced symbols

This is an immediate fix for #492, although #342 is needed to implement the
desired functionality.

--- a/include/asm/symbol.h
+++ b/include/asm/symbol.h
@@ -33,6 +33,7 @@
 	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;
--- a/src/asm/symbol.c
+++ b/src/asm/symbol.c
@@ -127,6 +127,7 @@
 	(*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 @@
 	return findsymbol(tzName, pscope);
 }
 
+static inline bool isReferenced(struct sSymbol const *sym)
+{
+	return sym->isReferenced;
+}
+
 /*
  * Purge a symbol
  */
@@ -230,6 +236,9 @@
 		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 @@
 	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 @@
 		nsym = createsymbol(tzSym);
 		nsym->type = SYM_REF;
 	}
+	nsym->isReferenced = true;
 }
 
 /*
--- /dev/null
+++ b/test/asm/purge-ref.asm
@@ -1,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
--- /dev/null
+++ b/test/asm/purge-ref.err
@@ -1,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)!