From a67f5d6e019252b37e2f6ab0e45b500f9e5e2a28 Mon Sep 17 00:00:00 2001 From: Rangi Date: Sun, 20 Jun 2021 16:10:27 -0400 Subject: [PATCH] SIZEOF("Section") and STARTOF("Section") can be known Fixes #890 --- include/asm/section.h | 3 +++ include/platform.h | 2 ++ src/asm/rpn.c | 36 +++++++++++++++++++---------- src/asm/section.c | 19 +++++++++++++++ test/asm/section-sizeof-startof.asm | 27 +++++++++++++++++++++- test/asm/section-sizeof-startof.err | 12 +++++++--- test/asm/section-sizeof-startof.out | 5 +++- 7 files changed, 87 insertions(+), 17 deletions(-) diff --git a/include/asm/section.h b/include/asm/section.h index eb244139..2ff5b156 100644 --- a/include/asm/section.h +++ b/include/asm/section.h @@ -13,6 +13,7 @@ #include #include "linkdefs.h" +#include "platform.h" // NONNULL extern uint8_t fillByte; @@ -76,4 +77,6 @@ void sect_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length); void sect_PushSection(void); void sect_PopSection(void); +bool sect_IsSizeKnown(struct Section const NONNULL(name)); + #endif diff --git a/include/platform.h b/include/platform.h index 091a1945..f6bdbf9e 100644 --- a/include/platform.h +++ b/include/platform.h @@ -49,8 +49,10 @@ /* MSVC doesn't support `[static N]` for array arguments from C99 */ #ifdef _MSC_VER # define MIN_NB_ELMS(N) +# define NONNULL(ptr) *ptr #else # define MIN_NB_ELMS(N) static (N) +# define NONNULL(ptr) ptr[static 1] #endif // MSVC uses a different name for O_RDWR, and needs an additional _O_BINARY flag diff --git a/src/asm/rpn.c b/src/asm/rpn.c index 1e0f5121..bcd4998b 100644 --- a/src/asm/rpn.c +++ b/src/asm/rpn.c @@ -205,28 +205,40 @@ void rpn_SizeOfSection(struct Expression *expr, char const *sectionName) { rpn_Init(expr); - makeUnknown(expr, "Section \"%s\"'s size is not known", sectionName); + struct Section *section = sect_FindSectionByName(sectionName); - size_t nameLen = strlen(sectionName) + 1; /* Room for NUL! */ - uint8_t *ptr = reserveSpace(expr, nameLen + 1); + if (section && sect_IsSizeKnown(section)) { + expr->val = section->size; + } else { + makeUnknown(expr, "Section \"%s\"'s size is not known", sectionName); - expr->rpnPatchSize += nameLen + 1; - *ptr++ = RPN_SIZEOF_SECT; - memcpy(ptr, sectionName, nameLen); + size_t nameLen = strlen(sectionName) + 1; /* Room for NUL! */ + uint8_t *ptr = reserveSpace(expr, nameLen + 1); + + expr->rpnPatchSize += nameLen + 1; + *ptr++ = RPN_SIZEOF_SECT; + memcpy(ptr, sectionName, nameLen); + } } void rpn_StartOfSection(struct Expression *expr, char const *sectionName) { rpn_Init(expr); - makeUnknown(expr, "Section \"%s\"'s start is not known", sectionName); + struct Section *section = sect_FindSectionByName(sectionName); - size_t nameLen = strlen(sectionName) + 1; /* Room for NUL! */ - uint8_t *ptr = reserveSpace(expr, nameLen + 1); + if (section && section->org != (uint32_t)-1) { + expr->val = section->org; + } else { + makeUnknown(expr, "Section \"%s\"'s start is not known", sectionName); - expr->rpnPatchSize += nameLen + 1; - *ptr++ = RPN_STARTOF_SECT; - memcpy(ptr, sectionName, nameLen); + size_t nameLen = strlen(sectionName) + 1; /* Room for NUL! */ + uint8_t *ptr = reserveSpace(expr, nameLen + 1); + + expr->rpnPatchSize += nameLen + 1; + *ptr++ = RPN_STARTOF_SECT; + memcpy(ptr, sectionName, nameLen); + } } void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src) diff --git a/src/asm/section.c b/src/asm/section.c index c9cf015f..2ba7490e 100644 --- a/src/asm/section.c +++ b/src/asm/section.c @@ -1016,3 +1016,22 @@ void sect_PopSection(void) sectionStack = entry->next; free(entry); } + +bool sect_IsSizeKnown(struct Section const NONNULL(sect)) +{ + // SECTION UNION and SECTION FRAGMENT can still grow + if (sect->modifier != SECTION_NORMAL) + return false; + + // The current section (or current load section if within one) is still growing + if (sect == currentSection || sect == currentLoadSection) + return false; + + // Any section on the stack is still growing + for (struct SectionStackEntry *stack = sectionStack; stack; stack = stack->next) { + if (stack->section && !strcmp(sect->name, stack->section->name)) + return false; + } + + return true; +} diff --git a/test/asm/section-sizeof-startof.asm b/test/asm/section-sizeof-startof.asm index 99e7c36e..371fae01 100644 --- a/test/asm/section-sizeof-startof.asm +++ b/test/asm/section-sizeof-startof.asm @@ -1,8 +1,33 @@ SECTION "sect", ROMX[$4567], BANK[$23] ds 42 +W = BANK("sect") +X = SIZEOF("sect") ; unknown +Y = STARTOF("sect") + + println "sect1: {W} {X} {Y}" + +SECTION "sect2", ROMX + W = BANK("sect") X = SIZEOF("sect") Y = STARTOF("sect") - println "{W} {X} {Y}" + println "sect1: {W} {X} {Y}" + +PUSHS +SECTION FRAGMENT "sect3", ROMX[$4567], BANK[$12] + +W = BANK("sect2") ; unknown +X = SIZEOF("sect2") ; unknown +Y = STARTOF("sect2") ; unknown + + println "sect2: {W} {X} {Y}" + +POPS + +W = BANK("sect3") +X = SIZEOF("sect3") ; unknown +Y = STARTOF("sect3") + + println "sect3: {W} {X} {Y}" diff --git a/test/asm/section-sizeof-startof.err b/test/asm/section-sizeof-startof.err index 8b8f95a9..ca9d923a 100644 --- a/test/asm/section-sizeof-startof.err +++ b/test/asm/section-sizeof-startof.err @@ -1,5 +1,11 @@ ERROR: section-sizeof-startof.asm(5): Expected constant expression: Section "sect"'s size is not known -ERROR: section-sizeof-startof.asm(6): - Expected constant expression: Section "sect"'s start is not known -error: Assembly aborted (2 errors)! +ERROR: section-sizeof-startof.asm(21): + Expected constant expression: Section "sect2"'s bank is not known +ERROR: section-sizeof-startof.asm(22): + Expected constant expression: Section "sect2"'s size is not known +ERROR: section-sizeof-startof.asm(23): + Expected constant expression: Section "sect2"'s start is not known +ERROR: section-sizeof-startof.asm(30): + Expected constant expression: Section "sect3"'s size is not known +error: Assembly aborted (5 errors)! diff --git a/test/asm/section-sizeof-startof.out b/test/asm/section-sizeof-startof.out index 5872dbfa..6d487a28 100644 --- a/test/asm/section-sizeof-startof.out +++ b/test/asm/section-sizeof-startof.out @@ -1 +1,4 @@ -$23 $0 $0 +sect1: $23 $0 $4567 +sect1: $23 $2A $4567 +sect2: $0 $0 $0 +sect3: $12 $0 $4567