public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Fangrui Song <i@maskray.me>
To: Jan Beulich <jbeulich@suse.com>
Cc: Binutils <binutils@sourceware.org>
Subject: Re: [PATCH] gas: extend \+ support to .rept
Date: Tue, 28 May 2024 22:40:21 -0700	[thread overview]
Message-ID: <DS7PR12MB576573CDCB223754A2894FC8CBF22@DS7PR12MB5765.namprd12.prod.outlook.com> (raw)
In-Reply-To: <CAN30aBGnGkS_vwC_23peBx9QJLSbejHU4PtYjY5NKOeESgLX5w@mail.gmail.com>

On Tue, May 28, 2024 at 10:21 PM Fangrui Song <i@maskray.me> wrote:
>
> On Mon, May 27, 2024 at 4:51 AM Jan Beulich <jbeulich@suse.com> wrote:
> >
> > PR gas/31752
> >
> > While not quite as macro-like as .irp / .irpc, this perhaps benefits from
> > supporting \+ even more than those: It allows, where desired, to get away
> > without maintaining an explicit count variable in source code.
> >
> > Keep .rep (and custom per-arch uses of s_rept() / do_repeat()) behavior
> > unaltered.
> >
> > --- a/gas/NEWS
> > +++ b/gas/NEWS
> > @@ -1,7 +1,7 @@
> >  -*- text -*-
> >
> > -* Assembler macros as well as the bodies of .irp / .irpc can now use the
> > -  syntax \+ to access the number of times a given macro has been executed.
> > +* Assembler macros as well as the bodies of .irp / .irpc / .rept 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.
> >
> > --- a/gas/doc/as.texi
> > +++ b/gas/doc/as.texi
> > @@ -6739,6 +6739,13 @@ is equivalent to assembling
> >  A count of zero is allowed, but nothing is generated.  Negative counts are not
> >  allowed and if encountered will be treated as if they were zero.
> >
> > +Much like for macros, @code{.irp}, and @code{.irpc} the @samp{\+} sequence can
> > +be used to substitute in the number of iterations done so far.  In such cases,
> > +i.e. when any @samp{\+} character sequence is present between @code{.rept} and
> > +the corresponding @code{.endr}, other backslashes also need escaping by
> > +backslashes.  Naturally the amount of escaping necessary may increase when
> > +using nested constructs.
> > +
> >  @node Sbttl
> >  @section @code{.sbttl "@var{subheading}"}
> >
> > --- a/gas/read.c
> > +++ b/gas/read.c
> > @@ -482,7 +482,7 @@ static const pseudo_typeS potable[] = {
> >    {"quad", cons, 8},
> >    {"reloc", s_reloc, 0},
> >    {"rep", s_rept, 0},
> > -  {"rept", s_rept, 0},
> > +  {"rept", s_rept, 1},
> >    {"rva", s_rva, 4},
> >    {"sbttl", listing_title, 1}, /* Subtitle of listing.  */
> >  /* scl  */
> > @@ -3066,19 +3066,21 @@ s_bad_end (int endr)
> >  /* Handle the .rept pseudo-op.  */
> >
> >  void
> > -s_rept (int ignore ATTRIBUTE_UNUSED)
> > +s_rept (int expand_count)
> >  {
> >    size_t count;
> >
> >    count = (size_t) get_absolute_expression ();
> >
> > -  do_repeat (count, "REPT", "ENDR", NULL);
> > +  do_repeat (count, "REPT", "ENDR", expand_count ? "" : NULL);
> >  }
> >
> >  /* This function provides a generic repeat block implementation.   It allows
> >     different directives to be used as the start/end keys.  Any text matching
> >     the optional EXPANDER in the block is replaced by the remaining iteration
> > -   count.  */
> > +   count.  Except when EXPANDER is the empty string, in which case \+ will
> > +   be looked for (as also recognized in macros as well as .irp and .irpc),
> > +   where the replacement will be the number of iterations done so far.  */
> >
> >  void
> >  do_repeat (size_t count, const char *start, const char *end,
> > @@ -3101,7 +3103,58 @@ do_repeat (size_t count, const char *sta
> >        return;
> >      }
> >
> > -  if (expander == NULL || strstr (one.ptr, expander) == NULL)
> > +  if (expander != NULL && !*expander && strstr (one.ptr, "\\+") != NULL)
> > +    {
> > +      /* The 3 here and below are arbitrary, added in an attempt to limit
> > +        re-allocation needs in sb_add_...() for moderate repeat counts.  */
> > +      sb_build (&many, count * (one.len + 3));
> > +
> > +      for (size_t done = 0; count-- > 0; ++done)

Nit: done = 0; done < count; ++done)  might be more idiomatic (avoid
changing `count`).

> > +       {
> > +         const char *ptr, *bs;
> > +         sb processed;
> > +
> > +         sb_build (&processed, one.len + 3);
> > +
> > +         for (ptr = one.ptr;
> > +              (bs = memchr (ptr, '\\', one.ptr + one.len - ptr)) != NULL; )
> > +           {
> > +             sb_add_buffer (&processed, ptr, bs - ptr);
> > +             switch (bs[1])
> > +               {
> > +                 char scratch[24];
> > +
> > +               default:
> > +                 sb_add_char (&processed, '\\');
> > +                 sb_add_char (&processed, bs[1]);
> > +                 ptr = bs + 2;
> > +                 break;
> > +
> > +               case '\0':
> > +                 as_warn (_("`\\' at end of line/statement; ignored"));
> > +                 ptr = bs + 1;
> > +                 break;
> > +
> > +               case '\\':
> > +                 sb_add_char (&processed, '\\');
> > +                 ptr = bs + 2;
> > +                 break;
> > +
> > +               case '+':
> > +                 snprintf (scratch, ARRAY_SIZE (scratch), "%zu", done);
> > +                 sb_add_string (&processed, scratch);
> > +                 ptr = bs + 2;
> > +                 break;
> > +               }
> > +           }
> > +
> > +         sb_add_buffer (&processed, ptr, one.ptr + one.len - ptr);
> > +
> > +         sb_add_sb (&many, &processed);
> > +         sb_kill (&processed);
> > +       }
> > +    }
> > +  else if (expander == NULL || !*expander || strstr (one.ptr, expander) == NULL)
> >      {
> >        sb_build (&many, count * one.len);
> >        while (count-- > 0)
> > --- a/gas/testsuite/gas/macros/macros.exp
> > +++ b/gas/testsuite/gas/macros/macros.exp
> > @@ -105,3 +105,4 @@ run_list_test altmacro
> >  run_list_test count
> >  run_list_test irp-count
> >  run_list_test irpc-quote
> > +run_list_test rept-count
> > --- /dev/null
> > +++ b/gas/testsuite/gas/macros/rept-count.l
> > @@ -0,0 +1,15 @@
> > +#...
> > +>0<
> > +>1<
> > +>2<
> > +>3<
> > +>4<
> > +>0<
> > +>0:0<
> > +>0:1<
> > +>1<
> > +>1:0<
> > +>1:1<
> > +>2<
> > +>2:0<
> > +>2:1<
> > --- /dev/null
> > +++ b/gas/testsuite/gas/macros/rept-count.s
> > @@ -0,0 +1,10 @@
> > +       .rept 5
> > +       .print ">\+<"
> > +       .endr
>
> LGTM.
>
> Perhaps this .print directive can be changed to print \+ \+
> to show that the \+ expanded value is identical within one iteration.
>
> > +
> > +       .rept 3
> > +       .print ">\+<"
> > +       .rept 2
> > +       .print ">\+:\\+<"
> > +       .endr
> > +       .endr

      parent reply	other threads:[~2024-05-29  5:47 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-27 11:51 Jan Beulich
2024-05-29  5:21 ` Fangrui Song
     [not found] ` <CAN30aBGnGkS_vwC_23peBx9QJLSbejHU4PtYjY5NKOeESgLX5w@mail.gmail.com>
2024-05-29  5:40   ` Fangrui Song [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DS7PR12MB576573CDCB223754A2894FC8CBF22@DS7PR12MB5765.namprd12.prod.outlook.com \
    --to=i@maskray.me \
    --cc=binutils@sourceware.org \
    --cc=jbeulich@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).