Skip to content

Commit

Permalink
Make ENDL optional like ENDSECTION (#1538)
Browse files Browse the repository at this point in the history
Add warning for `LOAD` without `ENDL`
  • Loading branch information
Rangi42 authored Oct 16, 2024
1 parent bc5a71f commit 3b32632
Show file tree
Hide file tree
Showing 21 changed files with 147 additions and 39 deletions.
1 change: 1 addition & 0 deletions contrib/bash_compl/_rgbasm.bash
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ _rgbasm_completions() {
shift-amount
truncation
unmapped-char
unterminated-load
user
all
extra
Expand Down
1 change: 1 addition & 0 deletions contrib/zsh_compl/_rgbasm
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ _rgbasm_warnings() {
'shift-amount:Warn when a shift'\''s operand it negative or \> 32'
'truncation:Warn when implicit truncation loses bits'
'unmapped-char:Warn on unmapped character'
'unterminated-load:Warn on LOAD without ENDL'
'user:Warn when executing the WARN built-in'
)
# TODO: handle `no-` and `error=` somehow?
Expand Down
3 changes: 2 additions & 1 deletion include/asm/section.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ void sect_SetLoadSection(
SectionSpec const &attrs,
SectionModifier mod
);
void sect_EndLoadSection();
void sect_EndLoadSection(char const *cause);
void sect_CheckLoadClosed();

Section *sect_GetSymbolSection();
uint32_t sect_GetSymbolOffset();
Expand Down
15 changes: 8 additions & 7 deletions include/asm/warning.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,21 @@ extern unsigned int nbErrors, maxErrors;

enum WarningID {
WARNING_ASSERT, // Assertions
WARNING_BACKWARDS_FOR, // `for` loop with backwards range
WARNING_BACKWARDS_FOR, // `FOR` loop with backwards range
WARNING_BUILTIN_ARG, // Invalid args to builtins
WARNING_CHARMAP_REDEF, // Charmap entry re-definition
WARNING_DIV, // Division undefined behavior
WARNING_DIV, // Undefined division behavior
WARNING_EMPTY_DATA_DIRECTIVE, // `db`, `dw` or `dl` directive without data in ROM
WARNING_EMPTY_MACRO_ARG, // Empty macro argument
WARNING_EMPTY_STRRPL, // Empty second argument in `STRRPL`
WARNING_LARGE_CONSTANT, // Constants too large
WARNING_MACRO_SHIFT, // Shift past available arguments in macro
WARNING_MACRO_SHIFT, // `SHIFT` past available arguments in macro
WARNING_NESTED_COMMENT, // Comment-start delimiter in a block comment
WARNING_OBSOLETE, // Obsolete things
WARNING_SHIFT, // Shifting undefined behavior
WARNING_SHIFT_AMOUNT, // Strange shift amount
WARNING_USER, // User warnings
WARNING_OBSOLETE, // Obsolete/deprecated things
WARNING_SHIFT, // Undefined `SHIFT` behavior
WARNING_SHIFT_AMOUNT, // Strange `SHIFT` amount
WARNING_UNTERMINATED_LOAD, // `LOAD` without `ENDL`
WARNING_USER, // User-defined `WARN`ings

NB_PLAIN_WARNINGS,

Expand Down
7 changes: 7 additions & 0 deletions man/rgbasm.1
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,13 @@ only warns if the active charmap is not empty.
.Fl Wunmapped-char=2
warns if the active charmap is empty, and/or is not the default charmap
.Sq main .
.It Fl Wunterminated-load
Warn when a
.Ic LOAD
block is not terminated by an
.Ic ENDL .
This warning is enabled by
.Fl Wextra .
.It Fl Wno-user
Warn when the
.Ic WARN
Expand Down
21 changes: 18 additions & 3 deletions man/rgbasm.5
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,7 @@ SECTION "LOAD example", ROMX
CopyCode:
ld de, RAMCode
ld hl, RAMLocation
ld c, RAMLocation.end - RAMLocation
ld c, RAMCode.end - RAMCode
\&.loop
ld a, [de]
inc de
Expand All @@ -927,8 +927,8 @@ RAMLocation:

\&.string
db "Hello World!\e0"
\&.end
ENDL
\&.end
.Ed
.Pp
A
Expand All @@ -938,7 +938,9 @@ block feels similar to a
declaration because it creates a new one.
All data and code generated within such a block is placed in the current section like usual, but all labels are created as if they were placed in this newly-created section.
.Pp
In the example above, all of the code and data will end up in the "LOAD example" section.
In the example above, all of the code and data will end up in the
.Dq LOAD example
section.
You will notice the
.Sq RAMCode
and
Expand All @@ -950,6 +952,19 @@ You cannot nest
.Ic LOAD
blocks, nor can you change or stop the current section within them.
.Pp
The current
.Ic LOAD
block can be ended by using
.Ic ENDL .
This directive is only necessary if you want to resume writing code in its containing ROM section.
Any of
.Ic LOAD , SECTION , ENDSECTION ,
or
.Ic POPS
will end the current
.Ic LOAD
block before performing its own function.
.Pp
.Ic LOAD
blocks can use the
.Ic UNION
Expand Down
1 change: 1 addition & 0 deletions src/asm/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ int main(int argc, char *argv[]) {
nbErrors = 1;

sect_CheckUnionClosed();
sect_CheckLoadClosed();
sect_CheckSizes();

if (nbErrors != 0)
Expand Down
2 changes: 1 addition & 1 deletion src/asm/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,7 @@ load:
sect_SetLoadSection($3, $5, $6, $7, $2);
}
| POP_ENDL {
sect_EndLoadSection();
sect_EndLoadSection(nullptr);
}
;

Expand Down
36 changes: 23 additions & 13 deletions src/asm/section.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,14 +425,14 @@ void sect_NewSection(
SectionSpec const &attrs,
SectionModifier mod
) {
if (currentLoadSection)
fatalerror("Cannot change the section within a `LOAD` block\n");

for (SectionStackEntry &entry : sectionStack) {
if (entry.section && entry.section->name == name)
fatalerror("Section '%s' is already on the stack\n", name.c_str());
}

if (currentLoadSection)
sect_EndLoadSection("SECTION");

Section *sect = getSection(name, type, org, attrs, mod);

changeSection();
Expand All @@ -457,11 +457,6 @@ void sect_SetLoadSection(
if (!requireCodeSection())
return;

if (currentLoadSection) {
error("`LOAD` blocks cannot be nested\n");
return;
}

if (sect_HasData(type)) {
error("`LOAD` blocks cannot create a ROM section\n");
return;
Expand All @@ -472,6 +467,9 @@ void sect_SetLoadSection(
return;
}

if (currentLoadSection)
sect_EndLoadSection("LOAD");

Section *sect = getSection(name, type, org, attrs, mod);

currentLoadLabelScopes = sym_GetCurrentLabelScopes();
Expand All @@ -481,7 +479,14 @@ void sect_SetLoadSection(
currentLoadSection = sect;
}

void sect_EndLoadSection() {
void sect_EndLoadSection(char const *cause) {
if (cause)
warning(
WARNING_UNTERMINATED_LOAD,
"`LOAD` block without `ENDL` terminated by `%s`\n",
cause
);

if (!currentLoadSection) {
error("Found `ENDL` outside of a `LOAD` block\n");
return;
Expand All @@ -494,6 +499,11 @@ void sect_EndLoadSection() {
sym_SetCurrentLabelScopes(currentLoadLabelScopes);
}

void sect_CheckLoadClosed() {
if (currentLoadSection)
warning(WARNING_UNTERMINATED_LOAD, "`LOAD` block without `ENDL` terminated by EOF\n");
}

Section *sect_GetSymbolSection() {
return currentLoadSection ? currentLoadSection : currentSection;
}
Expand Down Expand Up @@ -954,7 +964,7 @@ void sect_PopSection() {
fatalerror("No entries in the section stack\n");

if (currentLoadSection)
fatalerror("Cannot change the section within a `LOAD` block\n");
sect_EndLoadSection("POPS");

SectionStackEntry entry = sectionStack.front();
sectionStack.pop_front();
Expand All @@ -972,12 +982,12 @@ void sect_EndSection() {
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 (!currentUnionStack.empty())
fatalerror("Cannot end the section within a UNION\n");

if (currentLoadSection)
sect_EndLoadSection("ENDSECTION");

// Reset the section scope
currentSection = nullptr;
sym_ResetCurrentLabelScopes();
Expand Down
1 change: 1 addition & 0 deletions src/asm/warning.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ static const WarningFlag warningFlags[NB_WARNINGS] = {
{"obsolete", LEVEL_DEFAULT },
{"shift", LEVEL_EVERYTHING},
{"shift-amount", LEVEL_EVERYTHING},
{"unterminated-load", LEVEL_EXTRA },
{"user", LEVEL_DEFAULT },
// Parametric warnings
{"numeric-string", LEVEL_EVERYTHING},
Expand Down
7 changes: 5 additions & 2 deletions test/asm/endsection-in-load.err
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
FATAL: endsection-in-load.asm(3):
Cannot end the section within a `LOAD` block
warning: endsection-in-load.asm(3): [-Wunterminated-load]
`LOAD` block without `ENDL` terminated by `ENDSECTION`
error: endsection-in-load.asm(4):
Found `ENDL` outside of a `LOAD` block
error: Assembly aborted (1 error)!
51 changes: 51 additions & 0 deletions test/asm/load-endings.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
MACRO data
db SECTION(@), \#
ENDM

MACRO now_in
if strcmp("\1", "nothing")
assert !strcmp(SECTION(@), \1)
else
assert !def(@)
endc
ENDM

now_in nothing

SECTION "A", ROM0
now_in "A"
data 1
LOAD "P", WRAM0
now_in "P"
data 2

; LOAD after LOAD
LOAD "Q", WRAM0
now_in "Q"
data 3

; SECTION after LOAD
SECTION "B", ROM0
now_in "B"
data 4
LOAD "R", WRAM0
now_in "R"
data 5

; PUSHS after LOAD
PUSHS
SECTION "C", ROM0
now_in "C"
data 6
LOAD "S", WRAM0
now_in "S"
data 7

; POPS after LOAD
POPS
now_in "R"
data 8

; ENDSECTION after LOAD
ENDSECTION
now_in nothing
8 changes: 8 additions & 0 deletions test/asm/load-endings.err
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
warning: load-endings.asm(23): [-Wunterminated-load]
`LOAD` block without `ENDL` terminated by `LOAD`
warning: load-endings.asm(28): [-Wunterminated-load]
`LOAD` block without `ENDL` terminated by `SECTION`
warning: load-endings.asm(45): [-Wunterminated-load]
`LOAD` block without `ENDL` terminated by `POPS`
warning: load-endings.asm(50): [-Wunterminated-load]
`LOAD` block without `ENDL` terminated by `ENDSECTION`
1 change: 1 addition & 0 deletions test/asm/load-endings.out.bin
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BRRAPQCS
8 changes: 4 additions & 4 deletions test/asm/load-in-load.asm
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
SECTION "outer", ROM0
LOAD "inner", WRAM0
LOAD "matryoshka", HRAM
ENDL
ENDL
LOAD "inner1", WRAM0 ; starts "inner1"
LOAD "inner2", HRAM ; ends "inner1", starts "inner2"
ENDL ; ends "inner2"
ENDL ; error
6 changes: 3 additions & 3 deletions test/asm/load-in-load.err
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: load-in-load.asm(3):
`LOAD` blocks cannot be nested
warning: load-in-load.asm(3): [-Wunterminated-load]
`LOAD` block without `ENDL` terminated by `LOAD`
error: load-in-load.asm(5):
Found `ENDL` outside of a `LOAD` block
error: Assembly aborted (2 errors)!
error: Assembly aborted (1 error)!
2 changes: 1 addition & 1 deletion test/asm/nested-bad-interpolation.asm
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
def p = {{a}}
def q = "{b}"
def r = "{{c}}"
def r = "{{c}}"
4 changes: 2 additions & 2 deletions test/asm/section-in-load.asm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SECTION "outer", ROM0
SECTION "outer1", ROM0
LOAD "ram", WRAM0
SECTION "inner", ROM0
SECTION "outer2", ROM0
ENDL
7 changes: 5 additions & 2 deletions test/asm/section-in-load.err
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
FATAL: section-in-load.asm(3):
Cannot change the section within a `LOAD` block
warning: section-in-load.asm(3): [-Wunterminated-load]
`LOAD` block without `ENDL` terminated by `SECTION`
error: section-in-load.asm(4):
Found `ENDL` outside of a `LOAD` block
error: Assembly aborted (1 error)!
2 changes: 2 additions & 0 deletions test/asm/unterminated-load.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SECTION "rom", ROM0
LOAD "ram", WRAM0
2 changes: 2 additions & 0 deletions test/asm/unterminated-load.err
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
warning: unterminated-load.asm(3): [-Wunterminated-load]
`LOAD` block without `ENDL` terminated by EOF

0 comments on commit 3b32632

Please sign in to comment.