RFC: Maintaining a per-macro invocation count
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_binutils_build--master-arm |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_binutils_check--master-arm |
success
|
Testing passed
|
Commit Message
Hi Guys,
The attached patch implements a extension to the assembler's macro
syntax, allowing a macro to access a count of the number of times that
it has been executed via the \+ pseudo-variable. ie like this:
.macro foo
.print "I have been invoked \+ times"
.endm
This syntax is similar to the already supported \@ pseudo-variable,
except that the count is maintained on a per-macro basis.
The drive for this extension is that I want to be able to generate
N references to unique symbols in file A and then N definitions of
those symbols in file B. Using assembler macros makes this easy,
providing that I can ensure that the names in file A will match those
in file B. ie:
fileA.s:
.macro gen_refs count
.dc.a ref_\+
.if \count > 1
gen_refs \count-1
.endif
.endm
gen_refs 1000
fileB.s:
.macro gen_defs count
.global ref_\+
ref_\+ :
.if \count > 1
gen_defs \count-1
.endif
.endm
gen_defs 1000
(This is part of a larger exercise to generate some micro benchmarks
for the assembler that exercise various different features. In this
case I am looking into relocation processing).
Comments, suggestions ?
Cheers
Nick
PS. In the course of creating this patch I noticed that the altmacto
test (gas/testsuite/gas/macros/altmacro.d) does not appear to be run.
So I have fixed that as well.
Comments
> From: Nick Clifton <nickc@redhat.com>
> Date: Wed, 08 May 2024 18:11:13 +0100
Hi! Sorry for bringing bad news:
> Comments, suggestions ?
Sounds great except it appears you forgot to run this past
all targets. The new gas test doesn't work if the target
has '@' in line_separator_chars[] or tc_symbol_chars[], like
for cris-elf and mmix respectively:
Running /x/src/gas/testsuite/gas/macros/macros.exp ...
FAIL: macros count
A glance at gas.log for these targets shows that gas gets
confused and loses track, in different ways. Probably
fixable rather than requiring target-skipping for the test,
since the @ is "\-escaped", but I think I'd better leave
that to you.
brgds, H-P
On 2024-05-08, Nick Clifton wrote:
>Hi Guys,
>
> The attached patch implements a extension to the assembler's macro
> syntax, allowing a macro to access a count of the number of times that
> it has been executed via the \+ pseudo-variable. ie like this:
>
> .macro foo
> .print "I have been invoked \+ times"
> .endm
>
> This syntax is similar to the already supported \@ pseudo-variable,
> except that the count is maintained on a per-macro basis.
>
> The drive for this extension is that I want to be able to generate
> N references to unique symbols in file A and then N definitions of
> those symbols in file B. Using assembler macros makes this easy,
> providing that I can ensure that the names in file A will match those
> in file B. ie:
>
> fileA.s:
> .macro gen_refs count
> .dc.a ref_\+
> .if \count > 1
> gen_refs \count-1
> .endif
> .endm
>
> gen_refs 1000
>
> fileB.s:
> .macro gen_defs count
> .global ref_\+
> ref_\+ :
> .if \count > 1
> gen_defs \count-1
> .endif
> .endm
>
> gen_defs 1000
>
> (This is part of a larger exercise to generate some micro benchmarks
> for the assembler that exercise various different features. In this
> case I am looking into relocation processing).
(
I am curious how intrusive it would be to support a new relocation
format
https://maskray.me/blog/2024-03-09-a-compact-relocation-format-for-elf#crel-relocation-format
)
> Comments, suggestions ?
>
>Cheers
> Nick
>
>PS. In the course of creating this patch I noticed that the altmacto
>test (gas/testsuite/gas/macros/altmacro.d) does not appear to be run.
>So I have fixed that as well.
>
Thanks for the patch https://sourceware.org/cgit/binutils-gdb/commit/?id=83b972fc272db31ab48aa5cde84f47c98868d7c8
and the test fix!
This feature looks very useful, which resembles
https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Special-format-strings
> ‘%=’
>
> Outputs a number that is unique to each instance of the asm statement in
> the entire compilation. This option is useful when creating local labels
> and referring to them multiple times in a single template that generates
> multiple assembler instructions.
Hi Hans-Peter,
> Sounds great except it appears you forgot to run this past
> all targets. The new gas test doesn't work if the target
> has '@' in line_separator_chars[] or tc_symbol_chars[], like
> for cris-elf and mmix respectively:
Doh, sorry about that. I have now checked in small update
to fix the tests for the cris, mmix, and tic[4|5] targets.
Cheers
Nick
Hi Fangrui,
> This feature looks very useful, which resembles
> https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Special-format-strings
>
>> ‘%=’
>>
>> Outputs a number that is unique to each instance of the asm statement in
>> the entire compilation. This option is useful when creating local labels
>> and referring to them multiple times in a single template that generates
>> multiple assembler instructions.
Intersting. I had not considered generating assembler tests in C ... :-)
Cheers
Nick
On Wed, May 15, 2024 at 2:45 AM Nick Clifton <nickc@redhat.com> wrote:
>
> Hi Fangrui,
>
> > This feature looks very useful, which resembles
> > https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Special-format-strings
> >
> >> ‘%=’
> >>
> >> Outputs a number that is unique to each instance of the asm statement in
> >> the entire compilation. This option is useful when creating local labels
> >> and referring to them multiple times in a single template that generates
> >> multiple assembler instructions.
>
> Intersting. I had not considered generating assembler tests in C ... :-)
>
> Cheers
> Nick
>
Jan mentioned at https://sourceware.org/pipermail/binutils/2024-May/134087.html
> Just to mention it - I'm intending to extend \+ support to at least .irp
> and .irpc; whether that can also reasonably be done for .rept I haven't
> checked yet.
I filed https://sourceware.org/bugzilla/show_bug.cgi?id=31752 (gas:
Support \+ in .rept/.irp/.irpc directives) to formally track the
feature request
for loop directives.
@@ -1,5 +1,9 @@
-*- text -*-
+* Assembler macros can now use the syntax \+ to access the number of times a
+ given macro has been executed. This is similar to the already existing \@
+ syntax, except that the count is maintained on a per-macro basis.
+
* Support the NF feature in Intel APX.
* Remove KEYLOCKER and SHA promotions from EVEX MAP4.
@@ -6362,6 +6362,14 @@ Exit early from the current macro definition.
executed in this pseudo-variable; you can copy that number to your
output with @samp{\@@}, but @emph{only within a macro definition}.
+@cindex number of times a macro has been executed
+@cindex macro, execution count
+@item \+
+Similar to the @code{\@@} pseudo-variable, @command{@value{AS}} also maintains
+a per-macro count of the number of times that that macro has been executed.
+You can copy that number to your output with @samp{\+}, but
+@emph{only within a macro definition}.
+
@item LOCAL @var{name} [ , @dots{} ]
@emph{Warning: @code{LOCAL} is only available if you select ``alternate
macro syntax'' with @samp{--alternate} or @code{.altmacro}.}
@@ -56,7 +56,7 @@ int macro_defined;
/* Number of macro expansions that have been done. */
-static int macro_number;
+static unsigned int macro_number;
static void free_macro (macro_entry *);
@@ -668,6 +668,7 @@ define_macro (sb *in, sb *label, size_t (*get_line) (sb *))
macro->formal_count = 0;
macro->formals = 0;
macro->formal_hash = str_htab_create ();
+ macro->count = 0;
idx = sb_skip_white (0, in);
if (! buffer_and_nest ("MACRO", "ENDM", ¯o->sub, get_line))
@@ -846,11 +847,20 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals,
}
else if (src < in->len && in->ptr[src] == '@')
{
- /* Sub in the macro invocation number. */
+ /* Sub in the total macro invocation number. */
char buffer[12];
src++;
- sprintf (buffer, "%d", macro_number);
+ sprintf (buffer, "%u", macro_number);
+ sb_add_string (out, buffer);
+ }
+ else if (src < in->len && in->ptr[src] == '+')
+ {
+ /* Sub in the current macro invocation number. */
+
+ char buffer[12];
+ src++;
+ sprintf (buffer, "%d", macro->count);
sb_add_string (out, buffer);
}
else if (src < in->len && in->ptr[src] == '&')
@@ -1227,7 +1237,10 @@ macro_expand (size_t idx, sb *in, macro_entry *m, sb *out)
sb_kill (&t);
if (!err)
- macro_number++;
+ {
+ macro_number++;
+ m->count++;
+ }
return err;
}
@@ -60,13 +60,14 @@ typedef struct formal_struct {
typedef struct macro_struct
{
- sb sub; /* Substitution text. */
- int formal_count; /* Number of formal args. */
- formal_entry *formals; /* List of formal_structs. */
- htab_t formal_hash; /* Hash table of formals. */
- const char *name; /* Macro name. */
- const char *file; /* File the macro was defined in. */
- unsigned int line; /* Line number of definition. */
+ sb sub; /* Substitution text. */
+ int formal_count; /* Number of formal args. */
+ formal_entry * formals; /* List of formal_structs. */
+ htab_t formal_hash; /* Hash table of formals. */
+ const char * name; /* Macro name. */
+ const char * file; /* File the macro was defined in. */
+ unsigned int line; /* Line number of definition. */
+ unsigned int count; /* Invocation count. */
} macro_entry;
/* Whether any macros have been defined. */
@@ -1,3 +1,2 @@
-local
-.LL0001
-.LL0002
+#name: Local label generation in alternate macros (altmacro)
+
@@ -100,3 +100,6 @@ if [string match "" [lindex [gas_run ../all/excl.s "-o /dev/null" ""] 0]] {
# prevented the assembler from parsing the rest of the file,
# and hence catching an erroroneous instruction.
gas_test_error "exit.s" "" ".exitm outside of a macro"
+
+run_list_test altmacro
+run_list_test count
@@ -0,0 +1,3 @@
+local.*
+.*LL0001
+.*LL0002
@@ -0,0 +1,19 @@
+
+.macro mac1 count=10
+ .print "\@"
+ .print "\+"
+.if \count > 1
+ mac1 \count-1
+.endif
+.endm
+
+.macro mac2 count=100
+ .print "\@"
+ .print "\+"
+.if \count > 1
+ mac2 \count-1
+.endif
+.endm
+
+mac1 2
+mac2 3
@@ -0,0 +1,3 @@
+#name: Macro counters (count.d)
+# Tests that \@ counts total macro invocation count
+# and that \+ counts individual macro invocation count.
@@ -0,0 +1,10 @@
+0
+0
+1
+1
+2
+0
+3
+1
+4
+2