[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Bug gas/32391] \@ incorrectly handled in nested macros
From: |
regis.duchesne at broadcom dot com |
Subject: |
[Bug gas/32391] \@ incorrectly handled in nested macros |
Date: |
Thu, 28 Nov 2024 13:33:13 +0000 |
https://sourceware.org/bugzilla/show_bug.cgi?id=32391
--- Comment #2 from Regis Duchesne <regis.duchesne at broadcom dot com> ---
Hi Nick, thanks for looking at this bug.
> I think that this is more of a lack-of-documentation issue than a bug.
> Specifically - I would expect \@ to evaluate to the same number anywhere
> inside a macro, including any nested macros.
I respectfully disagree, I'll attempt below to argument in favor of my point of
view.
1) I agree that normally, an inner macro can use an argument of an outer macro
and see the same value.
For example this code
.macro outer arg
outer_\arg:
nop
.macro inner
inner_\arg:
nop
.endm
inner
.endm
outer foo
produces this output
outer_foo:
nop
inner_foo:
nop
i.e. the arg argument is visible/available to the inner macro, although it is
not explicitly an argument of the inner macro.
2) But I claim that \@ is special, and should be treated differently.
\@ is special because it is not an explicit argument. It is _implicitly_
created by each macro, when the macro starts executing, and given its value at
that moment in time.
\@ is also special because its _sole purpose_ (i.e. the reason it exists) is to
create unique names. If in my entire code base, I decide that by convention all
the labels defined in my macros will start with "_m\@_", then I should be
guaranteed that these labels never collide. But currently that is not what is
happening (and that is why I claim the current behavior is problematic):
For example this code
.macro outer
_m\@_:
nop
.endm
.macro inner
_m\@_:
nop
.endm
outer
inner
correctly produces this output:
_m0_:
nop
_m1_:
nop
but this code (the only change is that the inner macro goes inside the outer
one):
.macro outer
_m\@_:
nop
.macro inner
_m\@_:
nop
.endm
inner
.endm
outer
produces the error
Error: symbol `_m0_' is already defined
and that is completely unexpected: I just re-organized my code, but now it does
not assemble anymore! It goes against the principle of least surprise. Now I'm
in a bind: how should I name the label in my inner macro to guarantee no
collision? I could certainly adopt another label naming convention for all my
nested macros, but what if I don't know upfront whether a macro will be nested
or not? (In the case that prompted me to file this bug, the inner macro is
generated inside the outer macro with cpp.) What is the macro nesting is deeper
(a macro inside a macro inside a macro)? Should my label naming convention
depend on the level of nesting to avoid collisions? That is a bit insane, and
it does not scale.
So instead I claim that the output that should be produced should be the same
as if the macros were not nested, i.e.
_m0_:
nop
_m1_:
nop
3) Could the behavior I want prevent implementing Nick's example?
Not really. To implement Nick's example with the behavior I want, one can
always use an explicit parameter for the inner macro
.macro outer
before_inner_\@:
.macro inner label
.word \label
.end
inner before_inner_\@
inner before_inner_\@
.endm
outer
which will output the expected code.
4) Sad behavior of explicit nested arguments
To further make a point about what I wrote above "\@ is special because it is
not an explicit argument. It is _implicitly_ created by each macro, when the
macro starts executing", I wanted to show what would happen with an explicitly
named argument (with the same name) for both the outer and the inner macro. So
I tried this:
.macro outer arg
outer_\arg:
nop
.macro inner arg
inner_\arg:
nop
.endm
inner bar
.endm
outer foo
and I was extremely sad to discover that the output was
outer_foo:
nop
inner_foo:
nop
i.e. the value of the outer argument is given precedence over the value of the
inner argument! That seems completely _insane_ to me, and contrary to how all
languages handle local variables.
So while I realize that at least gas is consistent with how it deals with
arguments (whether they are explicitly named "arg" or implicitly named "@"), I
find the current gas behavior absolutely terrible, in that it does not scale:
it is _impossible_ to write a small piece of code in a macro, and have a
guarantee that it will always work. Depending on where that macro is actually
instantiated (such as inside another macro), that macro may not work.
So the problem I'm reporting is actually more generic than just \@. I should
have titled this bug "arguments with same name incorrectly handled in nested
macros".
If you tell me this is desirable behavior, well to me it is a big gotcha. To
the very least, that should be documented. But really, it should be fixed :)
Cheers, --RĂ©gis
--
You are receiving this mail because:
You are on the CC list for the bug.