diff --git a/src/asm/section.c b/src/asm/section.c index 15ac74ff..c9cf015f 100644 --- a/src/asm/section.c +++ b/src/asm/section.c @@ -20,12 +20,19 @@ uint8_t fillByte; +struct UnionStackEntry { + uint32_t start; + uint32_t size; + struct UnionStackEntry *next; +} *unionStack = NULL; + struct SectionStackEntry { struct Section *section; struct Section *loadSection; char const *scope; /* Section's symbol scope */ uint32_t offset; int32_t loadOffset; + struct UnionStackEntry *unionStack; struct SectionStackEntry *next; }; @@ -35,12 +42,6 @@ struct Section *currentSection = NULL; static struct Section *currentLoadSection = NULL; int32_t loadOffset; /* Offset into the LOAD section's parent (see sect_GetOutputOffset) */ -struct UnionStackEntry { - uint32_t start; - uint32_t size; - struct UnionStackEntry *next; -} *unionStack = NULL; - /* * A quick check to see if we have an initialized section */ @@ -428,6 +429,11 @@ void sect_NewSection(char const *name, uint32_t type, uint32_t org, void sect_SetLoadSection(char const *name, uint32_t type, uint32_t org, struct SectionSpec const *attribs, enum SectionModifier mod) { + // Important info: currently, UNION and LOAD cannot interact, since UNION is prohibited in + // "code" sections, whereas LOAD is restricted to them. + // Therefore, any interactions are NOT TESTED, so lift either of those restrictions at + // your own peril! ^^ + if (!checkcodesection()) return; @@ -548,6 +554,11 @@ static void createPatch(enum PatchType type, struct Expression const *expr, uint void sect_StartUnion(void) { + // Important info: currently, UNION and LOAD cannot interact, since UNION is prohibited in + // "code" sections, whereas LOAD is restricted to them. + // Therefore, any interactions are NOT TESTED, so lift either of those restrictions at + // your own peril! ^^ + if (!currentSection) { error("UNIONs must be inside a SECTION\n"); return; @@ -964,22 +975,24 @@ cleanup: */ void sect_PushSection(void) { - struct SectionStackEntry *sect = malloc(sizeof(*sect)); + struct SectionStackEntry *entry = malloc(sizeof(*entry)); - if (sect == NULL) + if (entry == NULL) fatalerror("No memory for section stack: %s\n", strerror(errno)); - sect->section = currentSection; - sect->loadSection = currentLoadSection; - sect->scope = sym_GetCurrentSymbolScope(); - sect->offset = curOffset; - sect->loadOffset = loadOffset; - sect->next = sectionStack; - sectionStack = sect; + entry->section = currentSection; + entry->loadSection = currentLoadSection; + entry->scope = sym_GetCurrentSymbolScope(); + entry->offset = curOffset; + entry->loadOffset = loadOffset; + entry->unionStack = unionStack; + entry->next = sectionStack; + sectionStack = entry; // Reset the section scope currentSection = NULL; currentLoadSection = NULL; sym_SetCurrentSymbolScope(NULL); + unionStack = NULL; } void sect_PopSection(void) @@ -998,6 +1011,7 @@ void sect_PopSection(void) sym_SetCurrentSymbolScope(entry->scope); curOffset = entry->offset; loadOffset = entry->loadOffset; + unionStack = entry->unionStack; sectionStack = entry->next; free(entry); diff --git a/test/asm/union-pushs.asm b/test/asm/union-pushs.asm new file mode 100644 index 00000000..5d074af8 --- /dev/null +++ b/test/asm/union-pushs.asm @@ -0,0 +1,25 @@ + +SECTION "Test", ROM0[0] + dw SIZEOF("RAM") + dw SIZEOF("HRAM") + +SECTION "RAM",WRAM0 + ds 654 +UNION + ds 14 +NEXTU + ds 897 + +PUSHS + +SECTION "HRAM",HRAM + ds $7F + +POPS + ds 75 +NEXTU + ds 863 +ENDU + + ds 28 + diff --git a/test/asm/union-pushs.err b/test/asm/union-pushs.err new file mode 100644 index 00000000..e69de29b diff --git a/test/asm/union-pushs.out b/test/asm/union-pushs.out new file mode 100644 index 00000000..e69de29b diff --git a/test/asm/union-pushs.out.bin b/test/asm/union-pushs.out.bin new file mode 100644 index 00000000..28748fa7 Binary files /dev/null and b/test/asm/union-pushs.out.bin differ