gas: Revert PR 32391 related commits to fix 3 regressions

9f2e3c21f6 Fix the handling or arguments and macro pseudo-variables inside nested assembler macros.

introduced 3 regressions of PR gas/32484, PR gas/32486 and PR gas/32487.
Revert all PR 32391 related commits and add tests for PR gas/32484,
PR gas/32486, PR gas/32487.

	PR gas/32484
	PR gas/32486
	PR gas/32487
	* testsuite/gas/macros/macros.exp: Run nesting1, nesting2 and
	nesting3.
	* testsuite/gas/macros/nesting1.d: New file.
	* testsuite/gas/macros/nesting1.s: Likewise.
	* testsuite/gas/macros/nesting2.d: Likewise.
	* testsuite/gas/macros/nesting2.s: Likewise.
	* testsuite/gas/macros/nesting3.d: Likewise.
	* testsuite/gas/macros/nesting3.s: Likewise.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
This commit is contained in:
H.J. Lu
2025-01-02 06:09:30 +08:00
parent 434deed44d
commit f087e2e3f6
15 changed files with 126 additions and 445 deletions

View File

@@ -105,6 +105,8 @@ struct iq2000_hi_fixup
/* The list of unmatched HI relocs. */
static struct iq2000_hi_fixup * iq2000_hi_fixup_list;
/* Macro hash table, which we will add to. */
extern struct htab *macro_hash;
const char md_shortopts[] = "";
const struct option md_longopts[] =
@@ -277,7 +279,9 @@ iq2000_add_macro (const char * name,
}
}
(void) add_macro (macro, true);
str_hash_insert (macro_hash, macro->name, macro, 1);
macro_defined = 1;
}
static void

View File

@@ -6215,12 +6215,7 @@ With that definition, @samp{SUM 0,5} is equivalent to this assembly input:
@item .macro @var{macname}
@itemx .macro @var{macname} @var{macargs} @dots{}
@cindex @code{macro} directive
Begin the definition of a macro called @var{macname}. Macro names are case
insensitive. Macro definitions can be nested, although their behaviour is
sometimes counter intuitive. Nested macros only have scope within their
defining macro.
If your macro
Begin the definition of a macro called @var{macname}. If your macro
definition requires arguments, specify their names after the macro name,
separated by commas or spaces. You can qualify the macro argument to
indicate whether all invocations must specify a non-blank value (through
@@ -6385,29 +6380,6 @@ adjacent string literals - even if separated only by a blank - will not be
concatenated when determining macro arguments, even if they're only separated
by white space. This is unlike certain other pseudo ops, e.g. @code{.ascii}.
Nested macros can access the arguments of their parents. But also if their
argument names clash with those of their parents, their versions are used. So
for example:
@smallexample
.macro OUTER arg1, arg2, arg3:vararg
.macro INNER arg4 arg2
.dc.a \arg2
.dc.a \arg3
.endm
INNER \arg1 bert
.dc.a \arg2
.endm
OUTER fred, jim, harry\arg4
@end smallexample
This will generate references to symbols called @samp{jim} - from the
definition of the OUTER macro, @samp{bert} - from the definition in INNER
where arg2 has been overridden and @samp{harryfred} - from the definition in
INNER where the value of arg3 from OUTER is used, but with the value of arg4
substituted into the symbol.
@item .endm
@cindex @code{endm} directive
Mark the end of a macro definition.
@@ -6423,33 +6395,6 @@ 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}.
Note - the @samp{\@@} counter is incremented at the end of the expansion of a
macro, but before the contents of any nested macros are evaluated. This can
lead to counter-intuitive behaviour when nested macros are used. For example:
@smallexample
.macro o
.macro i
_i\@@_:
.endm
i
_o\@@_:
.endm
o
@end smallexample
Produces two symbols @samp{_o0_} and @samp{_i1_}. This happens because the
@samp{o} macro executes entirely first, putting the definition and invocation
of the @samp{i} macro into the input buffer. It also puts the definition of
the @samp{_o\@@_} symbol into the input buffer, evaluating the @samp{\@@}
counter in the process and so generating a symbol called @samp{_o0_}.
That finishes the invocation of @samp{o} so the @samp{\@@} counter is
incremented. Then the input buffer is re-evaluated and the definition and
invocation of macro @samp{i} is found. This results in @samp{_i\@@_} being put
into the input buffer and this time @samp{\@@} evaluates to 1, so the symbol
created is @samp{_i1_}.
@cindex number of times a macro has been executed
@cindex macro, execution count
@item \+
@@ -6736,9 +6681,6 @@ those explicitly specified with @code{.eject}.
Undefine the macro @var{name}, so that later uses of the string will not be
expanded. @xref{Macro}.
Note - nested macros are automatically purged at the end of the macro that
defines them.
@ifset ELF
@node PushSection
@section @code{.pushsection @var{name} [, @var{subsection}] [, "@var{flags}"[, @@@var{type}[,@var{arguments}]]]}

View File

@@ -23,7 +23,6 @@
#include "input-file.h"
#include "sb.h"
#include "listing.h"
#include "macro.h"
/*
* O/S independent module to supply buffers of sanitised source code
@@ -291,13 +290,12 @@ input_scrub_include_sb (sb *from, char *position, enum expansion expansion)
++macro_nest;
}
#ifdef md_macro_start
if (expansion == expanding_macro)
{
#ifdef md_macro_start
md_macro_start ();
#endif
increment_macro_nesting_depth ();
}
#endif
next_saved_file = input_scrub_push (position);
@@ -352,7 +350,6 @@ input_scrub_next_buffer (char **bufp)
data. */
md_macro_end ();
#endif
decrement_macro_nesting_depth ();
}
if (from_sb_expansion != expanding_app)
--macro_nest;

View File

@@ -44,24 +44,11 @@
/* The macro hash table. */
/* Macro nesting depth. Similar to macro_nest defined in sb.c, but this
counter is specific to macros, whereas macro_nest also counts repeated
string blocks. */
static unsigned int macro_nesting_depth;
htab_t macro_hash;
/* Maximum nesting depth. Ideally the same as the value of max_macro_nest
as defined in as.c (ie 100). But there is one test in the assembler
testsuite (bfin/allinsn16.s) that nests macros to a depth of 8192. So
we have a ridiculously large number here. */
#define MAX_MACRO_DEPTH 8193
/* Whether any macros have been defined. */
static htab_t macro_hash[MAX_MACRO_DEPTH];
/* Whether any macros have been defined.
FIXME: This could be a counter that is incremented
with .macro and decremented with .purgem. */
static bool macros_defined = false;
int macro_defined;
/* Whether we should strip '@' characters. */
@@ -73,18 +60,6 @@ static unsigned int macro_number;
static void free_macro (macro_entry *);
bool
add_macro (macro_entry * macro, bool replace)
{
if (str_hash_insert (macro_hash [macro_nesting_depth],
macro->name, macro, replace) == NULL)
{
macros_defined = true;
return true;
}
return false;
}
static void
macro_del_f (void *ent)
{
@@ -97,23 +72,15 @@ macro_del_f (void *ent)
void
macro_init (void)
{
int i;
for (i = 0; i < MAX_MACRO_DEPTH; i++)
macro_hash[i] = htab_create_alloc (16, hash_string_tuple, eq_string_tuple,
macro_del_f, notes_calloc, NULL);
macros_defined = false;
macro_hash = htab_create_alloc (16, hash_string_tuple, eq_string_tuple,
macro_del_f, notes_calloc, NULL);
macro_defined = 0;
}
void
macro_end (void)
{
int i;
for (i = MAX_MACRO_DEPTH; i--;)
htab_delete (macro_hash[i]);
macros_defined = false;
htab_delete (macro_hash);
}
/* Read input lines till we get to a TO string.
@@ -688,13 +655,6 @@ free_macro (macro_entry *macro)
free (macro);
}
static macro_entry * last_recorded_macro = NULL;
void
macro_record_invocation (macro_entry * macro)
{
last_recorded_macro = macro;
}
/* Define a new macro. */
macro_entry *
@@ -758,19 +718,15 @@ define_macro (sb *in, sb *label, size_t (*get_line) (sb *))
/* And stick it in the macro hash table. */
for (idx = 0; idx < name.len; idx++)
name.ptr[idx] = TOLOWER (name.ptr[idx]);
if (macro_nesting_depth > 0)
macro->parent = last_recorded_macro;
else
macro->parent = NULL;
if (!error)
{
if (! add_macro (macro, false))
if (str_hash_insert (macro_hash, macro->name, macro, 0) != NULL)
error = _("Macro `%s' was already defined");
}
if (error != NULL)
if (!error)
macro_defined = 1;
else
{
as_bad_where (macro->file, macro->line, error, macro->name);
free_macro (macro);
@@ -794,25 +750,11 @@ get_apost_token (size_t idx, sb *in, sb *name, int kind)
return idx;
}
static const char *
macro_expand_body (sb *, sb *, formal_entry *, struct htab *,
const macro_entry *, unsigned int);
/* Find the actual value for a formal parameter starting at START inside IN.
Appends the value of parameter onto OUT.
The hash table of formal parameters is provided by FORMAL_HASH.
The character that indicated the presense of a formal parameter is passed
in KIND.
If COPYIFNOTTHERE is true and the parameter is not found in the hash table
then it is appended as plain text onto OUT.
The macro containing the formal parameters is passed in MACRO.
This can be empty.
Returns the offset inside IN after advanceing past the parameter.
Also stores the parameter's name into T. */
/* Substitute the actual value for a formal parameter. */
static size_t
sub_actual (size_t start, sb *in, sb *t, struct htab *formal_hash,
int kind, sb *out, int copyifnotthere, const macro_entry * macro)
int kind, sb *out, int copyifnotthere)
{
size_t src;
formal_entry *ptr;
@@ -826,12 +768,16 @@ sub_actual (size_t start, sb *in, sb *t, struct htab *formal_hash,
ptr = NULL;
else
ptr = str_hash_find (formal_hash, sb_terminate (t));
if (ptr)
{
sb * add = ptr->actual.len ? &ptr->actual : &ptr->def;
sb_add_sb (out, add);
if (ptr->actual.len)
{
sb_add_sb (out, &ptr->actual);
}
else
{
sb_add_sb (out, &ptr->def);
}
}
else if (kind == '&')
{
@@ -845,56 +791,6 @@ sub_actual (size_t start, sb *in, sb *t, struct htab *formal_hash,
{
sb_add_sb (out, t);
}
else if (!macro_strip_at
&& macro_nesting_depth > 0
&& macro != NULL
&& macro->parent != NULL)
{
const macro_entry * orig_macro = macro;
bool success = false;
/* We have failed to find T, but we are inside nested macros. So check
the parent macros so see if they have a FORMAL that matches T. */
while (macro->parent != NULL)
{
macro = macro->parent;
ptr = str_hash_find (macro->formal_hash, t->ptr);
if (ptr == NULL)
continue;
sb * add = ptr->actual.len ? &ptr->actual : &ptr->def;
/* The parent's FORMALs might contain parameters that need further
substitution. See gas/testsuite/gas/arm/macro-vld1.s for an
example of this. */
if (memchr (add->ptr, '\\', add->len))
{
sb newadd;
sb_new (&newadd);
/* FIXME: Should we do something if the call to
macro_expand_body returns an error message ? */
(void) macro_expand_body (add, &newadd, NULL, NULL,
orig_macro, orig_macro->count);
sb_add_sb (out, &newadd);
sb_kill (&newadd);
}
else
{
sb_add_sb (out, add);
}
success = true;
break;
}
if (! success)
{
/* We reached the outermost macro and failed to find T, so
just copy the entire parameter as is. */
sb_add_char (out, '\\');
sb_add_sb (out, t);
}
}
else
{
sb_add_char (out, '\\');
@@ -903,12 +799,7 @@ sub_actual (size_t start, sb *in, sb *t, struct htab *formal_hash,
return src;
}
/* Expands the body of a macro / block of text IN, copying it into OUT.
Parameters for substitution are found in FORMALS and FORMAL_HASH or
MACRO.
The number of times that this macro / block of text have already been
copied into the output is held in INSTANCE.
Returns NULL upon success or an error message otherwise. */
/* Expand the body of a macro. */
static const char *
macro_expand_body (sb *in, sb *out, formal_entry *formals,
@@ -920,38 +811,18 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals,
int inquote = 0, macro_line = 0;
formal_entry *loclist = NULL;
const char *err = NULL;
int nesting = 0;
if (formals == NULL && macro != NULL)
formals = macro->formals;
if (formal_hash == NULL && macro != NULL)
formal_hash = macro->formal_hash;
sb_new (&t);
while (src < in->len && !err)
{
if (in->ptr[src] == '.')
{
/* Check to see if we have encountered ".macro" or ".endm" */
if (in->len > src + 5
&& strncmp (in->ptr + src, ".macro", 6) == 0)
++ nesting;
else if (in->len > src + 4
&& strncmp (in->ptr + src, ".endm", 5) == 0)
-- nesting;
}
if (in->ptr[src] == '&')
{
sb_reset (&t);
if (flag_mri)
{
if (src + 1 < in->len && in->ptr[src + 1] == '&')
src = sub_actual (src + 2, in, &t, formal_hash,
'\'', out, 1, macro);
src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1);
else
sb_add_char (out, in->ptr[src++]);
}
@@ -959,8 +830,7 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals,
{
/* Permit macro parameter substitution delineated with
an '&' prefix and optional '&' suffix. */
src = sub_actual (src + 1, in, &t, formal_hash,
'&', out, 0, macro);
src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
}
}
else if (in->ptr[src] == '\\')
@@ -981,12 +851,7 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals,
else
as_bad_where (macro->file, macro->line + macro_line, _("missing `)'"));
}
else if (src < in->len
&& in->ptr[src] == '@'
/* PR 32391: Do not perform the substition inside nested
macros. Instead wait until they are re-evaluated and
perform the substition then. */
&& ! nesting)
else if (src < in->len && in->ptr[src] == '@')
{
/* Sub in the total macro invocation number. */
@@ -995,12 +860,7 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals,
sprintf (buffer, "%u", macro_number);
sb_add_string (out, buffer);
}
else if (src < in->len
&& in->ptr[src] == '+'
/* PR 32391: Do not perform the substition inside nested
macros. Instead wait until they are re-evaluated and
perform the substition then. */
&& ! nesting)
else if (src < in->len && in->ptr[src] == '+')
{
/* Sub in the current macro invocation number. */
@@ -1044,18 +904,7 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals,
else
{
sb_reset (&t);
if (nesting)
{
src = get_apost_token (src, in, &t, '\'');
sb_add_char (out, '\\');
sb_add_sb (out, &t);
}
else
{
src = sub_actual (src, in, &t, formal_hash,
'\'', out, 0, macro);
}
src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
}
}
else if ((flag_macro_alternate || flag_mri)
@@ -1074,7 +923,7 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals,
sb_reset (&t);
src = sub_actual (src, in, &t, formal_hash,
(macro_strip_at && inquote) ? '@' : '\'',
out, 1, macro);
out, 1);
}
else
{
@@ -1186,7 +1035,6 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals,
if (!err && (out->len == 0 || out->ptr[out->len - 1] != '\n'))
sb_add_char (out, '\n');
return err;
}
@@ -1371,7 +1219,8 @@ macro_expand (size_t idx, sb *in, macro_entry *m, sb *out)
}
}
err = macro_expand_body (&m->sub, out, NULL, NULL, m, m->count);
err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, m,
m->count);
}
/* Discard any unnamed formal arguments. */
@@ -1404,22 +1253,20 @@ macro_expand (size_t idx, sb *in, macro_entry *m, sb *out)
}
/* Check for a macro. If one is found, put the expansion into
*EXPAND. Return TRUE if a macro is found, FALSE otherwise. */
*EXPAND. Return 1 if a macro is found, 0 otherwise. */
bool
int
check_macro (const char *line, sb *expand,
const char **error, macro_entry **info)
{
const char *s;
char *copy, *cls;
macro_entry *macro;
sb line_sb;
if (! macros_defined)
return false;
if (! is_name_beginner (*line)
&& (! flag_mri || *line != '.'))
return false;
return 0;
s = line + 1;
while (is_part_of_name (*s))
@@ -1431,17 +1278,11 @@ check_macro (const char *line, sb *expand,
for (cls = copy; *cls != '\0'; cls ++)
*cls = TOLOWER (*cls);
macro_entry *macro = NULL;
for (int i = macro_nesting_depth; i >= 0; i--)
{
macro = str_hash_find (macro_hash[i], copy);
if (macro != NULL)
break;
}
macro = str_hash_find (macro_hash, copy);
free (copy);
if (macro == NULL)
return false;
return 0;
/* Wrap the line up in an sb. */
sb_new (&line_sb);
@@ -1457,7 +1298,7 @@ check_macro (const char *line, sb *expand,
if (info)
*info = macro;
return true;
return 1;
}
/* Delete a macro. */
@@ -1475,20 +1316,11 @@ delete_macro (const char *name)
copy[i] = TOLOWER (name[i]);
copy[i] = '\0';
int j;
for (j = macro_nesting_depth; j >= 0; j--)
{
macro = str_hash_find (macro_hash [j], copy);
if (macro != NULL)
{
str_hash_delete (macro_hash[j], copy);
break;
}
}
if (j < 0)
macro = str_hash_find (macro_hash, copy);
if (macro != NULL)
str_hash_delete (macro_hash, copy);
else
as_warn (_("Attempt to purge non-existing macro `%s'"), copy);
free (copy);
}
@@ -1590,25 +1422,3 @@ expand_irp (int irpc, size_t idx, sb *in, sb *out, size_t (*get_line) (sb *))
return err;
}
void
increment_macro_nesting_depth (void)
{
if (macro_nesting_depth >= (MAX_MACRO_DEPTH - 1))
as_fatal (_("macros nested too deeply"));
else
++macro_nesting_depth;
}
void
decrement_macro_nesting_depth (void)
{
if (macro_nesting_depth == 0)
as_fatal (_("too much macro un-nesting"));
else
{
/* FIXME: Potential memory leak here. */
htab_empty (macro_hash [macro_nesting_depth]);
--macro_nesting_depth;
}
}

View File

@@ -64,28 +64,31 @@ typedef struct macro_struct
int formal_count; /* Number of formal args. */
formal_entry * formals; /* List of formal_structs. */
htab_t formal_hash; /* Hash table of formals. */
struct macro_struct * parent; /* Parent of nested macros. */
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;
/* The macro/text block nesting level. */
/* Whether any macros have been defined. */
extern int macro_defined;
/* The macro nesting level. */
extern int macro_nest;
/* The macro hash table. */
extern htab_t macro_hash;
extern int buffer_and_nest (const char *, const char *, sb *,
size_t (*) (sb *));
extern void macro_init (void);
extern void macro_end (void);
extern macro_entry *define_macro (sb *, sb *, size_t (*) (sb *));
extern bool check_macro (const char *, sb *, const char **, macro_entry **);
extern int check_macro (const char *, sb *, const char **, macro_entry **);
extern void delete_macro (const char *);
extern const char *expand_irp (int, size_t, sb *, sb *, size_t (*) (sb *));
extern void increment_macro_nesting_depth (void);
extern void decrement_macro_nesting_depth (void);
extern void macro_record_invocation (macro_entry *);
extern bool add_macro (macro_entry *, bool);
#endif

View File

@@ -656,8 +656,7 @@ poend (void)
}
/* Helper function of read_a_source_file, which tries to expand a macro. */
static bool
static int
try_macro (char term, const char *line)
{
sb out;
@@ -674,14 +673,12 @@ try_macro (char term, const char *line)
sb_kill (&out);
buffer_limit =
input_scrub_next_buffer (&input_line_pointer);
macro_record_invocation (macro);
#ifdef md_macro_info
md_macro_info (macro);
#endif
return true;
return 1;
}
return false;
return 0;
}
#ifdef HANDLE_BUNDLE
@@ -1273,7 +1270,7 @@ read_a_source_file (const char *name)
s_ignore (0);
nul_char = next_char = *--input_line_pointer;
*input_line_pointer = '\0';
if (! try_macro (next_char, s))
if (! macro_defined || ! try_macro (next_char, s))
{
*end = '\0';
as_bad (_("unknown pseudo-op: `%s'"), s);
@@ -1310,7 +1307,7 @@ read_a_source_file (const char *name)
generate_lineno_debug ();
if (try_macro (next_char, s))
if (macro_defined && try_macro (next_char, s))
continue;
if (mri_pending_align)
@@ -2820,7 +2817,7 @@ s_macro (int ignore ATTRIBUTE_UNUSED)
as_warn_where (macro->file, macro->line,
_("attempt to redefine pseudo-op `%s' ignored"),
macro->name);
delete_macro (macro->name);
str_hash_delete (macro_hash, macro->name);
}
}

View File

@@ -112,4 +112,6 @@ run_list_test count
run_list_test irp-count
run_list_test irpc-quote
run_list_test rept-count
run_dump_test nesting
run_dump_test nesting1
run_dump_test nesting2
run_dump_test nesting3

View File

@@ -1,28 +0,0 @@
#nm: -j
#name: Nested macros (PR 32391)
# Sone targets do not support macros used like this.
#skip: tic*-*-* mmix-*
#...
_m7_
_m8_
after_at_0
after_at_3
after_plus_0
after_plus_1
before_at_0
before_at_3
before_plus_0
before_plus_1
bert
harryfred
i3_bar
inside_at_1
inside_at_2
inside_at_4
inside_at_5
inside_plus_0
inside_plus_1
jim
o3_foo
other_inner_6

View File

@@ -1,104 +0,0 @@
.text
/* PR 32391: Automatic counters inside macros should increment when nested
macros finish execution. */
.macro o1
.global before_at_\@
before_at_\@:
.global before_plus_\+
before_plus_\+:
.macro i1
.global inside_at_\@
inside_at_\@:
.global inside_plus_\+
inside_plus_\+:
.endm
i1
i1
.global after_at_\@
after_at_\@:
.global after_plus_\+
after_plus_\+:
.endm
/* Invoking o1 should produce these symbols in this order:
before_at_0
before_plus_0
inside_at_1
inside_plus_0
inside_at_2
inside_plus_1
after_at_0
after_plus_0 */
o1
/* A second invocation of o1 should not produce any errors about
symbols or macros being redefined. */
o1
/* This definition should not collide with the definition inside o1. */
.macro i1
.global other_inner_\@
other_inner_\@:
.endm
/* And invoking it should invoke the second defintion of i1, not the first. */
i1
.macro o2
.global _m\@_
_m\@_:
.macro i2
.global _m\@_
_m\@_:
.endm
i2
.endm
/* This should not generate conflicting symbols because the assembler
inserts the contents of o2 into the input buffer as pure text (ie
without evaluating i2). The first use of \@ is evaluated at this
time, creating _m4_. But the second use is not evaluated because
it is inside a .macro definition.
This finishes the evaluation of o2, so the \@ counter is incremented.
Next the input buffer is re-evaluated and the i2 macro definition
and invocation are encounterd. The text from i2 are inserted into
the input buffer and at this point the second use of \@ is evaluated
resulting in the creation of a symbol called _m5_. */
o2
/* Macro arguments should be independent of nesting. */
.macro O3 arg
.global o3_\arg
o3_\arg:
.macro I3 arg
.global i3_\arg
i3_\arg:
.endm
i3 bar /* Macro names are case insensitive. */
.endm
o3 foo /* Should produce two labels: o3_foo and i3_bar. */
/* Nested macros can access the arguments of their parents.
In addition their arguments can be substituted into the arguments
that are substited from their parents: */
.macro OUTER arg1, arg2, arg3:vararg
.macro INNER arg4 arg2
.dc.a \arg2
.dc.a \arg3
.endm
INNER \arg1 bert
.dc.a \arg2
.endm
/* This produces references to "jim", "bert" and "harryfred". */
OUTER fred, jim, harry\arg4

View File

@@ -0,0 +1,7 @@
#nm: -j
#name: Nested macros (PR 32484)
# Sone targets do not support macros used like this.
#skip: mmix-*
#...
foo

View File

@@ -0,0 +1,14 @@
.text
.macro entry fname
\fname:
.endm
.macro func fname, t
entry \fname
.macro data
.dc.\()\t 0
.endm
data
.endm
func foo, a

View File

@@ -0,0 +1,7 @@
#nm: -j
#name: Nested macros (PR 32486)
# Sone targets do not support macros used like this.
#skip: mmix-*
#...
foo

View File

@@ -0,0 +1,10 @@
.macro function name
.macro endfunc
.endm
.text
\name:
.endm
function foo
.dc.a 0
endfunc

View File

@@ -0,0 +1,7 @@
#nm: -j
#name: Nested macros (PR 32487)
# Sone targets do not support macros used like this.
#skip: mmix-*
#...
foo

View File

@@ -0,0 +1,13 @@
.text
.macro func
foo
.endm
.macro do_foo
.macro foo
foo:
.dc.a 0
.endm
.endm
do_foo
func