nesdev.com
http://forums.nesdev.com/

ca65: cheap local labels weirdness
http://forums.nesdev.com/viewtopic.php?f=2&t=16592
Page 1 of 1

Author:  tokumaru [ Wed Oct 18, 2017 3:07 pm ]
Post subject:  ca65: cheap local labels weirdness

Yesterday I was trying to do something using cheap local labels, and ran into something really weird. Here's a piece of code using cheap local labels:

Code:
BlockStart:

@LocalLabel:
   .byte $47

BlockEnd:

   lda @LocalLabel

As expected, an error occurs when trying to lda @LocalLabel, because the label is no longer visible.

However, I was writing the global labels from within macros, where I was doing other tasks, and mysteriously enough, the local label became visible outside of the block! After hours of debugging, I found the culprit, a symbol assignment using .set. Then I reproduced the issue in a more concise way:

Code:
BlockStart:
SomeSymbol .set 4

@LocalLabel:
   .byte $47

BlockEnd:
SomeSymbol .set 5

   lda @LocalLabel

In this case, the local label is accessible outside of the "block" where it was defined! Weird as fuck! I can only guess it's because the local label was created under "SomeSymbol", so when "SomeSymbol" is used again, the assembler thinks it's still the same block.

Sounds like a bug to me, because the "BlockEnd" label should be ending the scope where "@LocalLabel" is accessible, and you shouldn't be able to go back to that scope. What do you think? Is this a bug or a feature?

Another thing that's bothering me that also involves cheap local labels is that you can't "copy" a cheap local label before it's defined, like you can with other types of labels. For example, this works:

Code:
.scope

GlobalCopy := LocalLabel

LocalLabel:
   .byte $47

.endscope

   lda GlobalCopy

But this doesn't:

Code:
BlockStart:

GlobalCopy := @LocalLabel

@LocalLabel:
   .byte $47

BlockEnd:

   lda GlobalCopy

It only works if you make the copy after the label is defined:

Code:
BlockStart:

@LocalLabel:
   .byte $47

GlobalCopy := @LocalLabel

BlockEnd:

   lda GlobalCopy

I wonder if the GlobalCopy := @LocalLabel line is also acting as a "cheap local scope" breaker, so that when used at the top it tries to access the scope created by "BlockStart", which is prematurely ended by the use of "GlobalCopy", so "@LocalLabel" actually exists in the next scope. I gotta do some tests to verify this.

Author:  tokumaru [ Wed Oct 18, 2017 5:16 pm ]
Post subject:  Re: ca65: cheap local labels weirdness

I'm still profoundly weirded out by the first problem, and believe it's indeed a bug, but the second issue appears to be caused by any assignments to symbols that are not cheap locals causing a cheap local scope change. I used to think that only traditional labels (i.e. name followed by colon) did it, but assignments done via =, := and .set do it too. The documentation did say that "As soon as a standard symbol is encountered, the cheap local symbol goes out of scope.", but I wasn't sure what they meant by "encountered" in this context... Now I see that standard symbols can be used as arguments, but assignments will cause a scope change.

Author:  dullahan [ Wed Oct 18, 2017 5:48 pm ]
Post subject:  Re: ca65: cheap local labels weirdness

This is interesting. I've looked into the ca65 source a bit to figure out what's going on, but don't know for sure yet. The variable assignments (=, := and .set) are unique in that the accompanying symbol is replaced by the symbol's constant expression during assembly as I understand it (https://github.com/cc65/cc65/blob/709ee ... try.c#L263) and then defined here (https://github.com/cc65/cc65/blob/709ee ... try.c#L179), but why the variable assignment changes the current scope I don't understand...

Page 1 of 1 All times are UTC - 7 hours
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/