shithub: rgbds

Download patch

ref: 14be01880d1df164268952285f54aa2b206f93ba
parent: 12b7cf3cd44a2e953ad58050c9565ad5c7ea544a
author: ISSOtm <eldredhabert0@gmail.com>
date: Sun Sep 6 15:18:10 EDT 2020

Move UNION code inside section.c

Improves organization and locality

--- a/include/asm/asm.h
+++ b/include/asm/asm.h
@@ -21,7 +21,6 @@
 #include "asm/localasm.h"
 #include "asm/symbol.h"
 
-#define MAXUNIONS	128
 #define MAXMACROARGS	99999
 #define MAXINCPATHS	128
 
@@ -29,9 +28,6 @@
 extern uint32_t nTotalLines;
 extern uint32_t nIFDepth;
 extern bool skipElif;
-extern uint32_t nUnionDepth;
-extern uint32_t unionStart[MAXUNIONS];
-extern uint32_t unionSize[MAXUNIONS];
 extern char tzCurrentFileName[_MAX_PATH + 1];
 extern struct Section *pCurrentSection;
 extern bool oDontExpandStrings;
--- a/include/asm/section.h
+++ b/include/asm/section.h
@@ -46,9 +46,13 @@
 
 struct Section *sect_GetSymbolSection(void);
 uint32_t sect_GetSymbolOffset(void);
-void sect_SetSymbolOffset(uint32_t ofs);
 uint32_t sect_GetOutputOffset(void);
 void sect_AlignPC(uint8_t alignment, uint16_t offset);
+
+void sect_StartUnion(void);
+void sect_NextUnionMember(void);
+void sect_EndUnion(void);
+void sect_CheckUnionClosed(void);
 
 void out_AbsByte(uint8_t b);
 void out_AbsByteGroup(uint8_t const *s, int32_t length);
--- a/src/asm/asmy.y
+++ b/src/asm/asmy.y
@@ -383,32 +383,6 @@
 	nLineNo--;
 }
 
-static void startUnion(void)
-{
-	if (!pCurrentSection)
-		fatalerror("UNIONs must be inside a SECTION");
-
-	uint32_t unionIndex = nUnionDepth;
-
-	nUnionDepth++;
-	if (nUnionDepth > MAXUNIONS)
-		fatalerror("Too many nested UNIONs");
-
-	unionStart[unionIndex] = sect_GetOutputOffset();
-	unionSize[unionIndex] = 0;
-}
-
-static void updateUnion(void)
-{
-	uint32_t unionIndex = nUnionDepth - 1;
-	uint32_t size = sect_GetOutputOffset() - unionStart[unionIndex];
-
-	if (size > unionSize[unionIndex])
-		unionSize[unionIndex] = size;
-
-	sect_SetSymbolOffset(unionStart[unionIndex]);
-}
-
 static size_t strlenUTF8(const char *s)
 {
 	size_t len = 0;
@@ -975,26 +949,13 @@
 		}
 ;
 
-union		: T_POP_UNION	{ startUnion(); }
+union		: T_POP_UNION	{ sect_StartUnion(); }
 ;
 
-nextu		: T_POP_NEXTU {
-			if (nUnionDepth <= 0)
-				fatalerror("Found NEXTU outside of a UNION construct");
-
-			updateUnion();
-		}
+nextu		: T_POP_NEXTU	{ sect_NextUnionMember(); }
 ;
 
-endu		: T_POP_ENDU {
-			if (nUnionDepth <= 0)
-				fatalerror("Found ENDU outside of a UNION construct");
-
-			updateUnion();
-
-			nUnionDepth--;
-			sect_SetSymbolOffset(unionStart[nUnionDepth] + unionSize[nUnionDepth]);
-		}
+endu		: T_POP_ENDU	{ sect_EndUnion(); }
 ;
 
 ds		: T_POP_DS uconst	{ out_Skip($2, true); }
--- a/src/asm/main.c
+++ b/src/asm/main.c
@@ -40,7 +40,7 @@
 char **cldefines;
 
 clock_t nStartClock, nEndClock;
-uint32_t nTotalLines, nIFDepth, nUnionDepth;
+uint32_t nTotalLines, nIFDepth;
 bool skipElif;
 uint32_t unionStart[128], unionSize[128];
 
@@ -534,7 +534,6 @@
 	nTotalLines = 0;
 	nIFDepth = 0;
 	skipElif = true;
-	nUnionDepth = 0;
 	sym_Init();
 	sym_SetExportAll(exportall);
 	fstk_Init(tzMainfile);
@@ -553,10 +552,7 @@
 		errx(1, "Unterminated IF construct (%" PRIu32 " levels)!",
 		     nIFDepth);
 
-	if (nUnionDepth != 0) {
-		errx(1, "Unterminated UNION construct (%" PRIu32 " levels)!",
-		     nUnionDepth);
-	}
+	sect_CheckUnionClosed();
 
 	double timespent;
 
--- a/src/asm/section.c
+++ b/src/asm/section.c
@@ -28,6 +28,12 @@
 static struct Section *currentLoadSection = NULL;
 uint32_t loadOffset; /* The offset of the LOAD section within its parent */
 
+struct UnionStackEntry {
+	uint32_t start;
+	uint32_t size;
+	struct UnionStackEntry *next;
+} *unionStack = NULL;
+
 /*
  * A quick check to see if we have an initialized section
  */
@@ -48,8 +54,6 @@
 	if (!sect_HasData(pCurrentSection->nType))
 		fatalerror("Section '%s' cannot contain code or data (not ROM0 or ROMX)",
 			   pCurrentSection->pzName);
-	else if (nUnionDepth > 0)
-		fatalerror("UNIONs cannot contain code or data");
 }
 
 static inline void checkSectionSize(struct Section const *sect, uint32_t size)
@@ -302,7 +306,7 @@
  */
 static void changeSection(void)
 {
-	if (nUnionDepth > 0)
+	if (unionStack)
 		fatalerror("Cannot change the section within a UNION");
 
 	sym_SetCurrentSymbolScope(NULL);
@@ -367,11 +371,6 @@
 	return curOffset;
 }
 
-void sect_SetSymbolOffset(uint32_t ofs)
-{
-	curOffset = ofs;
-}
-
 uint32_t sect_GetOutputOffset(void)
 {
 	return curOffset + loadOffset;
@@ -436,6 +435,56 @@
 	out_CreatePatch(type, expr, sect_GetOutputOffset());
 }
 
+void sect_StartUnion(void)
+{
+	if (!pCurrentSection)
+		fatalerror("UNIONs must be inside a SECTION");
+	if (sect_HasData(pCurrentSection->nType))
+		fatalerror("Cannot use UNION inside of ROM0 or ROMX sections");
+	struct UnionStackEntry *entry = malloc(sizeof(*entry));
+
+	if (!entry)
+		fatalerror("Failed to allocate new union stack entry: %s", strerror(errno));
+	entry->start = curOffset;
+	entry->size = 0;
+	entry->next = unionStack;
+	unionStack = entry;
+}
+
+static void endUnionMember(void)
+{
+	uint32_t memberSize = curOffset - unionStack->start;
+
+	if (memberSize > unionStack->size)
+		unionStack->size = memberSize;
+	curOffset = unionStack->start;
+}
+
+void sect_NextUnionMember(void)
+{
+	if (!unionStack)
+		fatalerror("Found NEXTU outside of a UNION construct");
+	endUnionMember();
+}
+
+void sect_EndUnion(void)
+{
+	if (!unionStack)
+		fatalerror("Found ENDU outside of a UNION construct");
+	endUnionMember();
+	curOffset += unionStack->size;
+	struct UnionStackEntry *next = unionStack->next;
+
+	free(unionStack);
+	unionStack = next;
+}
+
+void sect_CheckUnionClosed(void)
+{
+	if (unionStack)
+		fatalerror("Unterminated UNION construct!");
+}
+
 /*
  * Output an absolute byte
  */
@@ -469,9 +518,6 @@
 
 	if (!sect_HasData(pCurrentSection->nType)) {
 		growSection(skip);
-	} else if (nUnionDepth > 0) {
-		while (skip--)
-			writebyte(CurrentOptions.fillchar);
 	} else {
 		checkcodesection();
 		while (skip--)