public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Julian Waters <tanksherman27@gmail.com>
To: binutils@sourceware.org
Subject: [PATCH] Add the .seh_ifrepeat and .seh_ifnrepeat directives
Date: Fri, 30 Jun 2023 15:53:13 +0800	[thread overview]
Message-ID: <CAP2b4GMYH=czD31TwmNrqOjnRH1dOsPVo8Be9VN=_EiFQWitoQ@mail.gmail.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 7814 bytes --]

In SEH assembly blocks, certain blocks should only be emitted once or a
certain number of times, but there is no good way to do so currently. This
patch adds the .seh_ifrepeat and .seh_ifnrepeat directives, which are
conditional directives that track the number of times they appear in an
.seh_proc block and activate/deactivate their respective code branches if
they appear more or less than the specified number of times in the same
block, respectively, and can be used with the .else and .endif directives
seamlessly

From c963b6ff835548516866c1c2d73ab9ff66f24030 Mon Sep 17 00:00:00 2001
From: TheShermanTanker <tanksherman27@gmail.com>
Date: Fri, 30 Jun 2023 13:53:19 +0800
Subject: [PATCH] Add the .seh_ifrepeat and .seh_ifnrepeat directives

---
 gas/cond.c                | 37 ++++---------------------
 gas/cond.h                | 52 +++++++++++++++++++++++++++++++++++
 gas/config/obj-coff-seh.c | 57 +++++++++++++++++++++++++++++++++++++++
 gas/config/obj-coff-seh.h |  3 +++
 4 files changed, 117 insertions(+), 32 deletions(-)
 create mode 100644 gas/cond.h

diff --git a/gas/cond.c b/gas/cond.c
index 5523e92..925f232 100644
--- a/gas/cond.c
+++ b/gas/cond.c
@@ -24,43 +24,16 @@

 #include "obstack.h"

+#include "cond.h"
+
 /* This is allocated to grow and shrink as .ifdef/.endif pairs are
    scanned.  */
 struct obstack cond_obstack;

-struct file_line
-{
-  const char *file;
-  unsigned int line;
-};
-
-/* We push one of these structures for each .if, and pop it at the
-   .endif.  */
-
-struct conditional_frame
-{
-  /* The source file & line number of the "if".  */
-  struct file_line if_file_line;
-  /* The source file & line of the "else".  */
-  struct file_line else_file_line;
-  /* The previous conditional.  */
-  struct conditional_frame *previous_cframe;
-  /* Have we seen an else yet?  */
-  int else_seen;
-  /* Whether we are currently ignoring input.  */
-  int ignoring;
-  /* Whether a conditional at a higher level is ignoring input.
-     Set also when a branch of an "if .. elseif .." tree has matched
-     to prevent further matches.  */
-  int dead_tree;
-  /* Macro nesting level at which this conditional was created.  */
-  int macro_nest;
-};
-
-static void initialize_cframe (struct conditional_frame *cframe);
+void initialize_cframe (struct conditional_frame *cframe);
 static char *get_mri_string (int, int *);

-static struct conditional_frame *current_cframe = NULL;
+struct conditional_frame *current_cframe = NULL;

 /* Performs the .ifdef (test_defined == 1) and
    the .ifndef (test_defined == 0) pseudo op.  */
@@ -534,7 +507,7 @@ ignore_input (void)
   return (current_cframe != NULL) && (current_cframe->ignoring);
 }

-static void
+void
 initialize_cframe (struct conditional_frame *cframe)
 {
   memset (cframe, 0, sizeof (*cframe));
diff --git a/gas/cond.h b/gas/cond.h
new file mode 100644
index 0000000..d5c135f
--- /dev/null
+++ b/gas/cond.h
@@ -0,0 +1,53 @@
+/* cond.h - conditional assembly pseudo-ops, and .include
+   Copyright (C) 1990-2023 Free Software Foundation, Inc.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GAS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+struct file_line
+{
+  const char *file;
+  unsigned int line;
+};
+
+/* We push one of these structures for each .if, and pop it at the
+   .endif.  */
+
+struct conditional_frame
+{
+  /* The source file & line number of the "if".  */
+  struct file_line if_file_line;
+  /* The source file & line of the "else".  */
+  struct file_line else_file_line;
+  /* The previous conditional.  */
+  struct conditional_frame *previous_cframe;
+  /* Have we seen an else yet?  */
+  int else_seen;
+  /* Whether we are currently ignoring input.  */
+  int ignoring;
+  /* Whether a conditional at a higher level is ignoring input.
+     Set also when a branch of an "if .. elseif .." tree has matched
+     to prevent further matches.  */
+  int dead_tree;
+  /* Macro nesting level at which this conditional was created.  */
+  int macro_nest;
+};
+
+extern struct conditional_frame *current_cframe;
+
+void initialize_cframe (struct conditional_frame *cframe);
+
diff --git a/gas/config/obj-coff-seh.c b/gas/config/obj-coff-seh.c
index 7b4486a..5c13ad8 100644
--- a/gas/config/obj-coff-seh.c
+++ b/gas/config/obj-coff-seh.c
@@ -20,6 +20,10 @@

 #include "obj-coff-seh.h"

+#include "as.h"
+#include "cond.h"
+#include "obstack.h"
+

 /* Private segment collection list.  */
 struct seh_seg_list {
@@ -40,6 +44,9 @@ static void write_function_xdata (seh_context *);
 static void write_function_pdata (seh_context *);


+static unsigned int ifcount = 0;
+
+
 /* Build based on segment the derived .pdata/.xdata
    segment name containing origin segment's postfix name part.  */
 static char *
@@ -273,6 +280,54 @@ skip_whitespace_and_comma (int required)
   return 0;
 }

+static void
+obj_coff_seh_ifrepeat (int what)
+{
+
+  if (!verify_context (".seh_ifrepeat"))
+    return;
+
+  unsigned int specified;
+  struct conditional_frame cframe;
+
+  /* Leading whitespace is part of operand.  */
+  SKIP_WHITESPACE ();
+
+  if (*input_line_pointer == 0 || *input_line_pointer == '\n') {
+    as_bad (_(".seh_ifrepeat requires the count parameter"));
+    demand_empty_rest_of_line ();
+    return;
+  } else if (*input_line_pointer == '-') {
+    as_bad (_("Negative count passed to .seh_ifrepeat"));
+    return;
+  } else {
+    specified = atoi(input_line_pointer);
+    ignore_rest_of_line();
+  }
+
+  initialize_cframe (&cframe);
+
+  if (cframe.dead_tree) {
+    cframe.ignoring = 1;
+  } else {
+    if (what == 0) {
+      cframe.ignoring = specified > ifcount++;
+    } else if (what == 1) {
+      cframe.ignoring = specified <= ifcount++;
+    }
+  }
+
+  current_cframe =
+    (struct conditional_frame *) obstack_alloc (&cond_obstack, sizeof
cframe);
+  memcpy (current_cframe, &cframe, sizeof cframe);
+
+  if (LISTING_SKIP_COND ()
+      && cframe.ignoring
+      && (cframe.previous_cframe == NULL
+   || ! cframe.previous_cframe->ignoring))
+    listing_list (2);
+}
+
 /* Mark current context to use 32-bit instruction (arm).  */

 static void
@@ -434,6 +489,8 @@ obj_coff_seh_proc (int what ATTRIBUTE_UNUSED)
       return;
     }

+  ifcount = 0;
+
   seh_ctx_cur = XCNEW (seh_context);

   seh_ctx_cur->code_seg = now_seg;
diff --git a/gas/config/obj-coff-seh.h b/gas/config/obj-coff-seh.h
index 8d77bac..ee3c809 100644
--- a/gas/config/obj-coff-seh.h
+++ b/gas/config/obj-coff-seh.h
@@ -70,6 +70,8 @@
         {"seh_endprologue", obj_coff_seh_endprologue, 0}, \
         {"seh_setframe", obj_coff_seh_setframe, 0}, \
         {"seh_stackalloc", obj_coff_seh_stackalloc, 0}, \
+        {"seh_ifrepeat", obj_coff_seh_ifrepeat, 0}, \
+        {"seh_ifnrepeat", obj_coff_seh_ifrepeat, 1}, \
  {"seh_eh", obj_coff_seh_eh, 0}, \
  {"seh_32", obj_coff_seh_32, 1}, \
  {"seh_no32", obj_coff_seh_32, 0}, \
@@ -151,6 +153,7 @@ static void obj_coff_seh_proc  (int);
 static void obj_coff_seh_handler (int);
 static void obj_coff_seh_handlerdata (int);
 static void obj_coff_seh_code (int);
+static void obj_coff_seh_ifrepeat (int);

 #define UNDSEC bfd_und_section_ptr

-- 
2.35.1.windows.2

             reply	other threads:[~2023-06-30  7:53 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-30  7:53 Julian Waters [this message]
2023-06-30 18:00 Julian Waters

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='CAP2b4GMYH=czD31TwmNrqOjnRH1dOsPVo8Be9VN=_EiFQWitoQ@mail.gmail.com' \
    --to=tanksherman27@gmail.com \
    --cc=binutils@sourceware.org \
    /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).