ref: a67f5d6e019252b37e2f6ab0e45b500f9e5e2a28
parent: 06b57aa1ce8e69a9e4ef96317f65de85c0540c3a
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Sun Jun 20 12:10:27 EDT 2021
SIZEOF("Section") and STARTOF("Section") can be known Fixes #890
--- a/include/asm/section.h
+++ b/include/asm/section.h
@@ -13,6 +13,7 @@
#include <stdbool.h>
#include "linkdefs.h"
+#include "platform.h" // NONNULL
extern uint8_t fillByte;
@@ -75,5 +76,7 @@
void sect_PushSection(void);
void sect_PopSection(void);
+
+bool sect_IsSizeKnown(struct Section const NONNULL(name));
#endif
--- 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
--- a/src/asm/rpn.c
+++ b/src/asm/rpn.c
@@ -205,14 +205,20 @@
{
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)
@@ -219,14 +225,20 @@
{
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)
--- a/src/asm/section.c
+++ b/src/asm/section.c
@@ -1016,3 +1016,22 @@
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;
+}
--- a/test/asm/section-sizeof-startof.asm
+++ b/test/asm/section-sizeof-startof.asm
@@ -2,7 +2,32 @@
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}"
--- 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)!
--- a/test/asm/section-sizeof-startof.out
+++ b/test/asm/section-sizeof-startof.out
@@ -1,1 +1,4 @@
-$23 $0 $0
+sect1: $23 $0 $4567
+sect1: $23 $2A $4567
+sect2: $0 $0 $0
+sect3: $12 $0 $4567