diff --git a/gas/NEWS b/gas/NEWS index cb58ca8fb8d..0fbd244c518 100644 --- a/gas/NEWS +++ b/gas/NEWS @@ -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. diff --git a/gas/doc/as.texi b/gas/doc/as.texi index 42db11e91da..1fb97c4cd9f 100644 --- a/gas/doc/as.texi +++ b/gas/doc/as.texi @@ -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}.} diff --git a/gas/macro.c b/gas/macro.c index e2ee39bc209..72d869d317f 100644 --- a/gas/macro.c +++ b/gas/macro.c @@ -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; } diff --git a/gas/macro.h b/gas/macro.h index a12fb894bec..e87f64e70ca 100644 --- a/gas/macro.h +++ b/gas/macro.h @@ -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. */ diff --git a/gas/testsuite/gas/macros/altmacro.d b/gas/testsuite/gas/macros/altmacro.d index 49c04aa3f79..e9ca349e1c7 100644 --- a/gas/testsuite/gas/macros/altmacro.d +++ b/gas/testsuite/gas/macros/altmacro.d @@ -1,3 +1,2 @@ -local -.LL0001 -.LL0002 +#name: Local label generation in alternate macros (altmacro) + diff --git a/gas/testsuite/gas/macros/macros.exp b/gas/testsuite/gas/macros/macros.exp index 38e613f088a..3108f3fcd56 100644 --- a/gas/testsuite/gas/macros/macros.exp +++ b/gas/testsuite/gas/macros/macros.exp @@ -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 --- /dev/null 2024-05-08 09:06:03.744530866 +0100 +++ current/gas/testsuite/gas/macros/altmacro.l 2024-05-08 17:45:47.116122421 +0100 @@ -0,0 +1,3 @@ +local.* +.*LL0001 +.*LL0002 --- /dev/null 2024-05-08 09:06:03.744530866 +0100 +++ current/gas/testsuite/gas/macros/count.s 2024-05-08 17:35:31.770892104 +0100 @@ -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 --- /dev/null 2024-05-08 09:06:03.744530866 +0100 +++ current/gas/testsuite/gas/macros/count.d 2024-05-08 17:46:54.781255760 +0100 @@ -0,0 +1,3 @@ +#name: Macro counters (count.d) +# Tests that \@ counts total macro invocation count +# and that \+ counts individual macro invocation count. --- /dev/null 2024-05-08 09:06:03.744530866 +0100 +++ current/gas/testsuite/gas/macros/count.l 2024-05-08 17:45:35.497099524 +0100 @@ -0,0 +1,10 @@ +0 +0 +1 +1 +2 +0 +3 +1 +4 +2