Implement ENDSECTION (#1211)

This commit is contained in:
Rangi
2023-11-04 18:41:17 -04:00
committed by GitHub
parent 99727cbe99
commit 259ec58140
12 changed files with 44 additions and 9 deletions

View File

@@ -74,6 +74,7 @@ void sect_PCRelByte(struct Expression *expr, uint32_t pcShift);
void sect_BinaryFile(char const *s, int32_t startPos);
void sect_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length);
void sect_EndSection(void);
void sect_PushSection(void);
void sect_PopSection(void);

View File

@@ -714,6 +714,11 @@ SECTION "OAM Data",WRAM0,ALIGN[8] ;\ align to 256 bytes
SECTION "VRAM Data",ROMX,BANK[2],ALIGN[4] ;\ align to 16 bytes
.Ed
.El
.Pp
The current section can be ended without starting a new section by using
.Ic ENDSECTION .
This directive will clear the section context, so you can no longer write code until you start another section.
It can be useful to avoid accidentally defining code or data in the wrong section.
.Ss Section stack
.Ic POPS
and
@@ -785,7 +790,7 @@ The former is situated in ROM, where the code is stored, the latter in RAM, wher
.Pp
You cannot nest
.Ic LOAD
blocks, nor can you change the current section within them.
blocks, nor can you change or stop the current section within them.
.Pp
.Ic LOAD
blocks can use the

View File

@@ -258,7 +258,7 @@ size_t charmap_ConvertNext(char const **input, uint8_t **output)
*input);
if (codepointLen == 0)
error("Input string is not valid UTF-8!\n");
error("Input string is not valid UTF-8\n");
// OK because UTF-8 has no NUL in multi-byte chars
*input += codepointLen;

View File

@@ -569,7 +569,7 @@ void fstk_Init(char const *mainPath, size_t maxDepth)
struct LexerState *state = lexer_OpenFile(mainPath);
if (!state)
fatalerror("Failed to open main file!\n");
fatalerror("Failed to open main file\n");
lexer_SetState(state);
char const *fileName = lexer_GetFileName();
size_t len = strlen(fileName);

View File

@@ -217,6 +217,7 @@ static struct KeywordMapping {
{"DW", T_POP_DW},
{"DL", T_POP_DL},
{"SECTION", T_POP_SECTION},
{"ENDSECTION", T_POP_ENDSECTION},
{"PURGE", T_POP_PURGE},
{"RSRESET", T_POP_RSRESET},
@@ -572,7 +573,7 @@ struct KeywordDictNode {
uint16_t children[0x60 - ' '];
struct KeywordMapping const *keyword;
// Since the keyword structure is invariant, the min number of nodes is known at compile time
} keywordDict[370] = {0}; // Make sure to keep this correct when adding keywords!
} keywordDict[377] = {0}; // Make sure to keep this correct when adding keywords!
// Convert a char into its index into the dict
static uint8_t dictIndex(char c)

View File

@@ -632,6 +632,7 @@ enum {
%token T_POP_EXPORT "EXPORT"
%token T_POP_DB "DB" T_POP_DS "DS" T_POP_DW "DW" T_POP_DL "DL"
%token T_POP_SECTION "SECTION" T_POP_FRAGMENT "FRAGMENT"
%token T_POP_ENDSECTION "ENDSECTION"
%token T_POP_RB "RB" T_POP_RW "RW" // There is no T_POP_RL, only T_Z80_RL
%token T_POP_MACRO "MACRO"
%token T_POP_ENDM "ENDM"
@@ -936,6 +937,7 @@ directive : endc
| purge
| pops
| pushs
| endsection
| popo
| pusho
| opt
@@ -1056,6 +1058,9 @@ pops : T_POP_POPS { sect_PopSection(); }
pushs : T_POP_PUSHS { sect_PushSection(); }
;
endsection : T_POP_ENDSECTION { sect_EndSection(); }
;
fail : T_POP_FAIL string { fatalerror("%s\n", $2); }
;

View File

@@ -598,7 +598,7 @@ void sect_EndUnion(void)
void sect_CheckUnionClosed(void)
{
if (unionStack)
error("Unterminated UNION construct!\n");
error("Unterminated UNION construct\n");
}
// Output an absolute byte
@@ -965,7 +965,7 @@ void sect_PopSection(void)
fatalerror("No entries in the section stack\n");
if (currentLoadSection)
fatalerror("Cannot change the section within a `LOAD` block!\n");
fatalerror("Cannot change the section within a `LOAD` block\n");
struct SectionStackEntry *entry = sectionStack;
@@ -981,6 +981,22 @@ void sect_PopSection(void)
free(entry);
}
void sect_EndSection(void)
{
if (!currentSection)
fatalerror("Cannot end the section outside of a SECTION\n");
if (currentLoadSection)
fatalerror("Cannot end the section within a `LOAD` block\n");
if (unionStack)
fatalerror("Cannot end the section within a UNION\n");
// Reset the section scope
currentSection = NULL;
sym_SetCurrentSymbolScope(NULL);
}
bool sect_IsSizeKnown(struct Section const NONNULL(sect))
{
// SECTION UNION and SECTION FRAGMENT can still grow

View File

@@ -242,7 +242,7 @@ static void registerInput(char const *arg) {
printUsage();
exit(1);
} else if (arg[0] == '\0') { // Empty input path
fprintf(stderr, "FATAL: input image path cannot be empty!\n");
fprintf(stderr, "FATAL: input image path cannot be empty\n");
printUsage();
exit(1);
} else {

View File

@@ -109,8 +109,8 @@ void reverse() {
auto const tiles = readInto(options.output);
uint8_t tileSize = 8 * options.bitDepth;
if (tiles.size() % tileSize != 0) {
fatal("Tile data size must be a multiple of %" PRIu8 " bytes! (Read %zu)", tileSize,
tiles.size());
fatal("Tile data size (%zu bytes) is not a multiple of %" PRIu8 " bytes",
tiles.size(), tileSize);
}
// By default, assume tiles are not deduplicated, and add the (allegedly) trimmed tiles

4
test/asm/endsection.asm Normal file
View File

@@ -0,0 +1,4 @@
SECTION "test", ROM0
db 1
ENDSECTION
db 2

3
test/asm/endsection.err Normal file
View File

@@ -0,0 +1,3 @@
error: endsection.asm(4):
Cannot output data outside of a SECTION
error: Assembly aborted (1 error)!

0
test/asm/endsection.out Normal file
View File