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--)