Skip to content

Commit

Permalink
allow defining local labels for another scope
Browse files Browse the repository at this point in the history
fix gbdev#1157 for the following source code
```
section "hSAVE_locals",HRAM
func3.hSpam: ds 1  ; no longer produces an error
;.hEggs: ds 1      ; uncomment this to see the new error

section "demo",ROM0
func3:
  ldh a, [.hSpam]
  ret
```

Remove two errors:
- `Not currently in the scope of 'func3'`
- `Local label 'func3.hSpam' in main scope`

Add one error:
- `Relative local label '.hSpam' in main scope`

Add a switch to restore previous behavior in `include/asm/symbol.h`
```c
```

update tests of local label definition failure

now that local label definition is more lenient, fewer tests
should fail

begin removing issue number from test

Co-authored-by: Rangi <35663410+Rangi42@users.noreply.github.com>

treat ALLOW_LOCAL_LABEL_ANYWHERE as always on

- don't gate the new lenient behavior behind a build-time condition
- change "Relative local label" to "Unqualified local label"
  in an error message

realign tests of local labels with wrong parent

- repurpose test/asm/sym-scope from a test of producing correct
  errors to a successful test
- remove test/asm/local-wrong-parent because it is now a redundant
  successful test

based on suggestions by @Rangi42
  • Loading branch information
pinobatch committed Aug 19, 2023
1 parent 1689508 commit 4e9c4fa
Show file tree
Hide file tree
Showing 7 changed files with 14 additions and 43 deletions.
26 changes: 7 additions & 19 deletions src/asm/symbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,16 +525,14 @@ static struct Symbol *addLabel(char const *symName)
// Add a local (`.name` or `Parent.name`) relocatable symbol
struct Symbol *sym_AddLocalLabel(char const *symName)
{
if (!labelScope) {
error("Local label '%s' in main scope\n", symName);
return NULL;
}
assert(!strchr(labelScope, '.')); // Assuming no dots in `labelScope`
// Assuming no dots in `labelScope` if defined
assert(!labelScope || !strchr(labelScope, '.'));

char fullName[MAXSYMLEN + 1];
char const *localName = strchr(symName, '.');

assert(localName); // There should be at least one dot in `symName`

// Check for something after the dot in `localName`
if (localName[1] == '\0') {
fatalerror("'%s' is a nonsensical reference to an empty local label\n",
Expand All @@ -546,23 +544,13 @@ struct Symbol *sym_AddLocalLabel(char const *symName)
symName);

if (localName == symName) {
if (!labelScope) {
error("Unqualified local label '%s' in main scope\n", symName);
return NULL;
}
// Expand `symName` to the full `labelScope.symName` name
fullSymbolName(fullName, sizeof(fullName), symName, labelScope);
symName = fullName;
} else {
size_t i = 0;

// Find where `labelScope` and `symName` first differ
while (labelScope[i] && symName[i] == labelScope[i])
i++;

// Check that `symName` starts with `labelScope` and then a '.'
if (labelScope[i] != '\0' || symName[i] != '.') {
size_t parentLen = localName - symName;

assert(parentLen <= INT_MAX);
error("Not currently in the scope of '%.*s'\n", (int)parentLen, symName);
}
}

return addLabel(symName);
Expand Down
2 changes: 1 addition & 1 deletion test/asm/local-without-parent.err
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
error: local-without-parent.asm(2):
Local label '.test' in main scope
Unqualified local label '.test' in main scope
error: Assembly aborted (1 error)!
6 changes: 0 additions & 6 deletions test/asm/local-wrong-parent.asm

This file was deleted.

3 changes: 0 additions & 3 deletions test/asm/local-wrong-parent.err

This file was deleted.

Empty file removed test/asm/local-wrong-parent.out
Empty file.
11 changes: 6 additions & 5 deletions test/asm/sym-scope.asm
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
SECTION "Scopes", ROM0

; Neither of these should be created
.tooSoon
Nice.try
; Tests of injecting local labels into another label's scope.
; This construction is useful to define a subroutine's local variables
; in WRAM or HRAM.
Valid.syntax

Parent:
.loc
Expand All @@ -11,8 +12,8 @@ Parent.explicit
dw .explicit ; This should expand to the above


; None of the two locals below should manage to be created, being in the wrong scopes
; Note however that `Parentheses` begins with `Parent`, which string checks may fail to handle
; Note that `Parentheses` begins with `Parent`,
; which string checks may fail to handle

Parentheses.check

Expand Down
9 changes: 0 additions & 9 deletions test/asm/sym-scope.err
Original file line number Diff line number Diff line change
@@ -1,9 +0,0 @@
error: sym-scope.asm(4):
Local label '.tooSoon' in main scope
error: sym-scope.asm(5):
Local label 'Nice.try' in main scope
error: sym-scope.asm(17):
Not currently in the scope of 'Parentheses'
error: sym-scope.asm(21):
Not currently in the scope of 'Parent'
error: Assembly aborted (4 errors)!

0 comments on commit 4e9c4fa

Please sign in to comment.