Merge pull request #1358 from dmsc/issue-479

Fixes Issue 479 (ca65: can't reference .proc members before declaration)
This commit is contained in:
Bob Andrews
2025-10-05 15:39:56 +02:00
committed by GitHub
40 changed files with 349 additions and 7 deletions

View File

@@ -1319,6 +1319,11 @@ if you want to access the "other" symbol <tt/bar/, you would have to write:
.endscope .endscope
</verb></tscreen> </verb></tscreen>
The above example also shows that to search a scope that is not yet defined in
the code above the usage, you should use the namespace token (<tt/::/) and
specify the full scope name, to allow the assembler to create the scope at the
correct place.
<sect>Address sizes and memory models<label id="address-sizes"><p> <sect>Address sizes and memory models<label id="address-sizes"><p>

View File

@@ -646,10 +646,14 @@ static void StudySymbol (ExprNode* Expr, ExprDesc* D)
** about the address size, check higher lexical levels for a symbol ** about the address size, check higher lexical levels for a symbol
** with the same name and use its address size if we find such a ** with the same name and use its address size if we find such a
** symbol which is defined. ** symbol which is defined.
**
** Only do the search if the symbol is not in the current scope,
** assume scoped symbols can't be resolved in a different scope.
*/ */
AddrSize = GetSymAddrSize (Sym); AddrSize = GetSymAddrSize (Sym);
Parent = GetSymParentScope (Sym); Parent = GetSymParentScope (Sym);
if (AddrSize == ADDR_SIZE_DEFAULT && Parent != 0) { if (AddrSize == ADDR_SIZE_DEFAULT && Parent != 0 &&
Sym->Sym.Tab == CurrentScope) {
SymEntry* H = SymFindAny (Parent, GetSymName (Sym)); SymEntry* H = SymFindAny (Parent, GetSymName (Sym));
if (H) { if (H) {
AddrSize = GetSymAddrSize (H); AddrSize = GetSymAddrSize (H);

View File

@@ -94,11 +94,15 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
*/ */
Scope = SymFindAnyScope (CurrentScope, Name); Scope = SymFindAnyScope (CurrentScope, Name);
if (Scope == 0) { if (Scope == 0) {
/* Scope not found */ /* Scope not found, create a new scope here */
Scope = SymFindScope (CurrentScope, Name, SYM_ALLOC_NEW);
if (Scope == 0) {
SB_Terminate (FullName); SB_Terminate (FullName);
Error ("No such scope: `%m%p'", FullName); /* Scope not found */
Error ("Can't create scope: `%m%p'", FullName);
return 0; return 0;
} }
}
} else { } else {
@@ -136,10 +140,10 @@ SymTable* ParseScopedIdent (StrBuf* Name, StrBuf* FullName)
SB_Append (FullName, Name); SB_Append (FullName, Name);
/* Search for the child scope */ /* Search for the child scope */
Scope = SymFindScope (Scope, Name, SYM_FIND_EXISTING); Scope = SymFindScope (Scope, Name, SYM_ALLOC_NEW);
if (Scope == 0) { if (Scope == 0) {
/* Scope not found */ /* Scope not found */
Error ("No such scope: `%m%p'", FullName); Error ("Can't create scope: `%m%p'", FullName);
return 0; return 0;
} }

View File

@@ -218,6 +218,8 @@ void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type,
if (CurrentScope->Flags & ST_DEFINED) { if (CurrentScope->Flags & ST_DEFINED) {
Error ("Duplicate scope `%m%p'", ScopeName); Error ("Duplicate scope `%m%p'", ScopeName);
} }
/* Open the scope as we are entering it */
CurrentScope->Flags &= ~ST_CLOSED;
} else { } else {
CurrentScope = RootScope = NewSymTable (0, ScopeName); CurrentScope = RootScope = NewSymTable (0, ScopeName);
@@ -294,6 +296,8 @@ SymTable* SymFindScope (SymTable* Parent, const StrBuf* Name, SymFindAction Acti
/* Create a new scope if requested and we didn't find one */ /* Create a new scope if requested and we didn't find one */
if (*T == 0 && (Action & SYM_ALLOC_NEW) != 0) { if (*T == 0 && (Action & SYM_ALLOC_NEW) != 0) {
*T = NewSymTable (Parent, Name); *T = NewSymTable (Parent, Name);
/* Close the created scope, will be reopened if needed */
(*T)->Flags |= ST_CLOSED;
} }
/* Return the scope */ /* Return the scope */

View File

@@ -0,0 +1,16 @@
.org $800
symbol1 := * ; ::symbol1
.addr symbol1 ; ::symbol1
.scope scope1
symbol1 := * ; ::scope1::symbol1
.addr symbol1 ; ::scope1::symbol1
.addr ::symbol1 ; ::symbol1
.endscope
.addr symbol1 ; ::symbol1
.addr scope1::symbol1 ; ::scope1::symbol

View File

@@ -0,0 +1,7 @@
.scope outer
foo = 2
.scope inner
lda #foo
foo = 3
.endscope
.endscope

View File

@@ -0,0 +1,7 @@
.scope outer
foo = $1234
.scope inner
lda foo,x
foo = $12
.endscope
.endscope

View File

@@ -0,0 +1,7 @@
.scope outer
foo = $12
.scope inner
lda foo,x
foo = $1234
.endscope
.endscope

View File

@@ -0,0 +1,7 @@
.scope outer
foo = $12
.scope inner
lda a:foo,x
foo = $1234
.endscope
.endscope

View File

@@ -0,0 +1,6 @@
bar = 3
.scope foo
bar = 2
lda #::bar ; Access the global bar (which is 3)
.endscope

View File

@@ -0,0 +1,10 @@
.scope foo
bar = 3
.endscope
.scope outer
lda #foo::bar ; Will load 3, not 2!
.scope foo
bar = 2
.endscope
.endscope

View File

@@ -0,0 +1,18 @@
.scope foo
.scope outer
.scope inner
bar = 1
.endscope
.endscope
.scope another
.scope nested
lda #outer::inner::bar ; 1
.endscope
.endscope
.endscope
.scope outer
.scope inner
bar = 2
.endscope
.endscope

View File

@@ -0,0 +1,18 @@
.scope foo
.scope outer
.scope inner
bar = 1
.endscope
.endscope
.scope another
.scope nested
lda #::outer::inner::bar ; 2
.endscope
.endscope
.endscope
.scope outer
.scope inner
bar = 2
.endscope
.endscope

View File

@@ -0,0 +1,16 @@
.org $2000
.proc s1
symbol := $1
stx s1::s2::symbol
stx s2_symbol
.scope s2
symbol: .byte 0
.endscope
s2_symbol := s2::symbol
.endproc

View File

@@ -0,0 +1,17 @@
.org $800
.scope main
.proc foo
;; should all be the same
lda params__bar
lda params::bar
lda foo::params::bar
.proc params
bar: .byte 0
.endproc
params__bar := params::bar
.endproc
.endscope

View File

@@ -0,0 +1,16 @@
;;; Regression test to ensure that newly inferred scopes are closed.
.scope foo
start:
;; Since `bar` is not a known scope at this point, it is
;; inferred to be `::foo::bar`, and since `::foo::bar::start`
;; does not exist this will produce an error. Importantly,
;; it does not resolve to `::foo::start` which would be
;; incorrect.
jmp bar::start
.endscope
.scope bar
start:
rts
.endscope

Binary file not shown.

View File

@@ -0,0 +1,21 @@
ca65 Vx.xx - Git XXXXXXXXX
Main file : 300-scopes-basic.s
Current file: 300-scopes-basic.s
000000r 1
000000r 1 .org $800
000800 1
000800 1 symbol1 := * ; ::symbol1
000800 1 00 08 .addr symbol1 ; ::symbol1
000802 1
000802 1
000802 1 .scope scope1
000802 1 symbol1 := * ; ::scope1::symbol1
000802 1
000802 1 02 08 .addr symbol1 ; ::scope1::symbol1
000804 1 00 08 .addr ::symbol1 ; ::symbol1
000806 1 .endscope
000806 1
000806 1 00 08 .addr symbol1 ; ::symbol1
000808 1 02 08 .addr scope1::symbol1 ; ::scope1::symbol
000808 1

View File

@@ -0,0 +1 @@
<EFBFBD>

View File

@@ -0,0 +1,12 @@
ca65 Vx.xx - Git XXXXXXXXX
Main file : 301-nested-scopes.s
Current file: 301-nested-scopes.s
000000r 1 .scope outer
000000r 1 foo = 2
000000r 1 .scope inner
000000r 1 A9 03 lda #foo
000002r 1 foo = 3
000002r 1 .endscope
000002r 1 .endscope
000002r 1

Binary file not shown.

View File

@@ -0,0 +1,12 @@
ca65 Vx.xx - Git XXXXXXXXX
Main file : 302-scope-redefined.s
Current file: 302-scope-redefined.s
000000r 1 .scope outer
000000r 1 foo = $1234
000000r 1 .scope inner
000000r 1 BD 12 00 lda foo,x
000003r 1 foo = $12
000003r 1 .endscope
000003r 1 .endscope
000003r 1

View File

@@ -0,0 +1 @@
303-change-addressing-mode-error.s:4: Error: Range error (4660 not in [0..255])

View File

@@ -0,0 +1 @@
<EFBFBD>4

View File

@@ -0,0 +1,12 @@
ca65 Vx.xx - Git XXXXXXXXX
Main file : 304-fix-addressing-mode-error.s
Current file: 304-fix-addressing-mode-error.s
000000r 1 .scope outer
000000r 1 foo = $12
000000r 1 .scope inner
000000r 1 BD 34 12 lda a:foo,x
000003r 1 foo = $1234
000003r 1 .endscope
000003r 1 .endscope
000003r 1

View File

@@ -0,0 +1 @@
<EFBFBD>

View File

@@ -0,0 +1,11 @@
ca65 Vx.xx - Git XXXXXXXXX
Main file : 305-explicit-scope-reference.s
Current file: 305-explicit-scope-reference.s
000000r 1 bar = 3
000000r 1
000000r 1 .scope foo
000000r 1 bar = 2
000000r 1 A9 03 lda #::bar ; Access the global bar (which is 3)
000002r 1 .endscope
000002r 1

View File

@@ -0,0 +1 @@
<EFBFBD>

View File

@@ -0,0 +1,15 @@
ca65 Vx.xx - Git XXXXXXXXX
Main file : 306-scope-use-before-definition.s
Current file: 306-scope-use-before-definition.s
000000r 1 .scope foo
000000r 1 bar = 3
000000r 1 .endscope
000000r 1
000000r 1 .scope outer
000000r 1 A9 03 lda #foo::bar ; Will load 3, not 2!
000002r 1 .scope foo
000002r 1 bar = 2
000002r 1 .endscope
000002r 1 .endscope
000002r 1

View File

@@ -0,0 +1 @@
<EFBFBD>

View File

@@ -0,0 +1,23 @@
ca65 Vx.xx - Git XXXXXXXXX
Main file : 307-scope-chains.s
Current file: 307-scope-chains.s
000000r 1 .scope foo
000000r 1 .scope outer
000000r 1 .scope inner
000000r 1 bar = 1
000000r 1 .endscope
000000r 1 .endscope
000000r 1 .scope another
000000r 1 .scope nested
000000r 1 A9 01 lda #outer::inner::bar ; 1
000002r 1 .endscope
000002r 1 .endscope
000002r 1 .endscope
000002r 1
000002r 1 .scope outer
000002r 1 .scope inner
000002r 1 bar = 2
000002r 1 .endscope
000002r 1 .endscope
000002r 1

View File

@@ -0,0 +1 @@
<EFBFBD>

View File

@@ -0,0 +1,23 @@
ca65 Vx.xx - Git XXXXXXXXX
Main file : 308-global-scope-anchoring.s
Current file: 308-global-scope-anchoring.s
000000r 1 .scope foo
000000r 1 .scope outer
000000r 1 .scope inner
000000r 1 bar = 1
000000r 1 .endscope
000000r 1 .endscope
000000r 1 .scope another
000000r 1 .scope nested
000000r 1 A9 02 lda #::outer::inner::bar ; 2
000002r 1 .endscope
000002r 1 .endscope
000002r 1 .endscope
000002r 1
000002r 1 .scope outer
000002r 1 .scope inner
000002r 1 bar = 2
000002r 1 .endscope
000002r 1 .endscope
000002r 1

View File

@@ -0,0 +1,21 @@
ca65 Vx.xx - Git XXXXXXXXX
Main file : 309-namespace-path-vs-addressing-mode.s
Current file: 309-namespace-path-vs-addressing-mode.s
000000r 1 .org $2000
002000 1
002000 1 .proc s1
002000 1
002000 1 symbol := $1
002000 1
002000 1 8E 06 20 stx s1::s2::symbol
002003 1 8E 06 20 stx s2_symbol
002006 1
002006 1 .scope s2
002006 1 00 symbol: .byte 0
002007 1 .endscope
002007 1
002007 1 s2_symbol := s2::symbol
002007 1
002007 1 .endproc
002007 1

View File

@@ -0,0 +1,22 @@
ca65 Vx.xx - Git XXXXXXXXX
Main file : 310-create-in-current-scope.s
Current file: 310-create-in-current-scope.s
000000r 1 .org $800
000800 1
000800 1 .scope main
000800 1 .proc foo
000800 1
000800 1 ;; should all be the same
000800 1 AD 09 08 lda params__bar
000803 1 AD 09 08 lda params::bar
000806 1 AD 09 08 lda foo::params::bar
000809 1
000809 1 .proc params
000809 1 00 bar: .byte 0
00080A 1 .endproc
00080A 1 params__bar := params::bar
00080A 1
00080A 1 .endproc
00080A 1 .endscope
00080A 1

View File

@@ -0,0 +1 @@
311-close-new-scopes-error.s:10: Error: Symbol 'start' is undefined