shithub: rgbds

Download patch

ref: c01317e08dd94002f497f9a3ec65760ae3e1cddc
parent: a52a00a9ca7753ef41814b55878b510e8dc80b7b
author: Rangi <[email protected]>
date: Wed Aug 31 13:45:21 EDT 2022

Only increment the unique `\@` ID when it is first used per context (#1030)

This avoids changes to generated `\@` labels just by adding or
removing macros or loops which do not actually use `\@`.

Fixes #1019

--- a/src/asm/fstack.c
+++ b/src/asm/fstack.c
@@ -285,6 +285,9 @@
 	++contextDepth;
 	fstk_NewRecursionDepth(maxRecursionDepth); // Only checks if the max depth was exceeded
 
+	// Save the current `\@` value, to be restored when this context ends
+	contextStack->uniqueID = macro_GetUniqueID();
+
 	struct Context *context = malloc(sizeof(*context));
 
 	if (!context)
--- a/src/asm/macro.c
+++ b/src/asm/macro.c
@@ -6,7 +6,6 @@
  * SPDX-License-Identifier: MIT
  */
 
-#include <assert.h>
 #include <errno.h>
 #include <inttypes.h>
 #include <stdbool.h>
@@ -145,6 +144,10 @@
 
 char const *macro_GetUniqueIDStr(void)
 {
+	// Generate a new unique ID on the first use of `\@`
+	if (uniqueID == 0)
+		macro_SetUniqueID(++maxUniqueID);
+
 	return uniqueIDPtr;
 }
 
@@ -151,11 +154,9 @@
 void macro_SetUniqueID(uint32_t id)
 {
 	uniqueID = id;
-	if (id == 0) {
+	if (id == 0 || id == (uint32_t)-1) {
 		uniqueIDPtr = NULL;
 	} else {
-		if (uniqueID > maxUniqueID)
-			maxUniqueID = uniqueID;
 		// The buffer is guaranteed to be the correct size
 		// This is a valid label fragment, but not a valid numeric
 		sprintf(uniqueIDBuf, "_u%" PRIu32, id);
@@ -165,13 +166,15 @@
 
 uint32_t macro_UseNewUniqueID(void)
 {
-	macro_SetUniqueID(++maxUniqueID);
+	// A new ID will be generated on the first use of `\@`
+	macro_SetUniqueID(0);
 	return uniqueID;
 }
 
 uint32_t macro_UndefUniqueID(void)
 {
-	macro_SetUniqueID(0);
+	// No ID will be generated; use of `\@` is an error
+	macro_SetUniqueID((uint32_t)-1);
 	return uniqueID;
 }
 
--- /dev/null
+++ b/test/asm/unique-id-values.asm
@@ -1,0 +1,22 @@
+MACRO m
+  println "  m: \@"
+  for q, \#
+    if q % 2 == 0
+      println "    q = {d:q}: \@"
+    else
+      println "    q = {d:q}"
+    endc
+  endr
+  println "  (m: still \@)"
+ENDM
+
+for p, 10
+  if p % 3 == 0
+    println "p = {d:p}: \@"
+    m 3
+    m 3, 6
+    println " (p: still \@)"
+  else
+    println "p = {d:p}"
+  endc
+endr
--- /dev/null
+++ b/test/asm/unique-id-values.out
@@ -1,0 +1,54 @@
+p = 0: _u1
+  m: _u2
+    q = 0: _u3
+    q = 1
+    q = 2: _u4
+  (m: still _u2)
+  m: _u5
+    q = 3
+    q = 4: _u6
+    q = 5
+  (m: still _u5)
+ (p: still _u1)
+p = 1
+p = 2
+p = 3: _u7
+  m: _u8
+    q = 0: _u9
+    q = 1
+    q = 2: _u10
+  (m: still _u8)
+  m: _u11
+    q = 3
+    q = 4: _u12
+    q = 5
+  (m: still _u11)
+ (p: still _u7)
+p = 4
+p = 5
+p = 6: _u13
+  m: _u14
+    q = 0: _u15
+    q = 1
+    q = 2: _u16
+  (m: still _u14)
+  m: _u17
+    q = 3
+    q = 4: _u18
+    q = 5
+  (m: still _u17)
+ (p: still _u13)
+p = 7
+p = 8
+p = 9: _u19
+  m: _u20
+    q = 0: _u21
+    q = 1
+    q = 2: _u22
+  (m: still _u20)
+  m: _u23
+    q = 3
+    q = 4: _u24
+    q = 5
+  (m: still _u23)
+ (p: still _u19)