public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r11-8642] inline-asm: Fix ICE with bitfields in "m" operands [PR100785]
@ 2021-06-23 13:19 Jakub Jelinek
  0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2021-06-23 13:19 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:b6e4453172e6502318d31517b7d3771b157ae71a

commit r11-8642-gb6e4453172e6502318d31517b7d3771b157ae71a
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Mon Jun 21 13:30:42 2021 +0200

    inline-asm: Fix ICE with bitfields in "m" operands [PR100785]
    
    Bitfields, while they live in memory, aren't something inline-asm can easily
    operate on.
    For C and "=m" or "+m", we were diagnosing bitfields in the past in the
    FE, where c_mark_addressable had:
          case COMPONENT_REF:
            if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
              {
                error
                  ("cannot take address of bit-field %qD", TREE_OPERAND (x, 1));
                return false;
              }
    but that check got moved in GCC 6 to build_unary_op instead and now we
    emit an error during expansion and ICE afterwards (i.e. error-recovery).
    For "m" it used to be diagnosed in c_mark_addressable too, but since
    GCC 6 it is ice-on-invalid.
    For C++, this was never diagnosed in the FE, but used to be diagnosed
    in the gimplifier and/or during expansion before 4.8.
    
    The following patch does multiple things:
    1) diagnoses it in the FEs
    2) simplifies during expansion the inline asm if any errors have been
       reported (similarly how e.g. vregs pass if it detects errors on
       inline-asm either deletes them or simplifies to bare minimum -
       just labels), so that we don't have error-recovery ICEs there
    
    2021-06-11  Jakub Jelinek  <jakub@redhat.com>
    
            PR inline-asm/100785
    gcc/
            * cfgexpand.c (expand_asm_stmt): If errors are emitted,
            remove all inputs, outputs and clobbers from the asm and
            set template to "".
    gcc/c/
            * c-typeck.c (c_mark_addressable): Diagnose trying to make
            bit-fields addressable.
    gcc/cp/
            * typeck.c (cxx_mark_addressable): Diagnose trying to make
            bit-fields addressable.
    gcc/testsuite/
            * c-c++-common/pr100785.c: New test.
    
    (cherry picked from commit 644c2cc5f2c09506a7bfef293a7f90efa8d7e5fa)

Diff:
---
 gcc/c/c-typeck.c                      | 11 ++++++++-
 gcc/cfgexpand.c                       | 43 ++++++++++++++++++++++++++++-------
 gcc/cp/typeck.c                       |  7 +++++-
 gcc/testsuite/c-c++-common/pr100785.c | 21 +++++++++++++++++
 4 files changed, 72 insertions(+), 10 deletions(-)

diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 917e670ddd7..7b84f3e6456 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -5033,8 +5033,17 @@ c_mark_addressable (tree exp, bool array_ref_p)
 	    && TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
 	    && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))))
 	  return true;
-	/* FALLTHRU */
+	x = TREE_OPERAND (x, 0);
+	break;
+
       case COMPONENT_REF:
+	if (DECL_C_BIT_FIELD (TREE_OPERAND (x, 1)))
+	  {
+	    error ("cannot take address of bit-field %qD",
+		   TREE_OPERAND (x, 1));
+	    return false;
+	  }
+	/* FALLTHRU */
       case ADDR_EXPR:
       case ARRAY_REF:
       case REALPART_EXPR:
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index c221b4165ca..0c26337bfa3 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -3076,6 +3076,7 @@ expand_asm_stmt (gasm *stmt)
   unsigned ninputs = gimple_asm_ninputs (stmt);
   unsigned nlabels = gimple_asm_nlabels (stmt);
   unsigned i;
+  bool error_seen = false;
 
   /* ??? Diagnose during gimplification?  */
   if (ninputs + noutputs + nlabels > MAX_RECOG_OPERANDS)
@@ -3134,6 +3135,7 @@ expand_asm_stmt (gasm *stmt)
 		{
 		  /* ??? Diagnose during gimplification?  */
 		  error ("unknown register name %qs in %<asm%>", regname);
+		  error_seen = true;
 		}
 	      else if (j == -4)
 		{
@@ -3196,7 +3198,10 @@ expand_asm_stmt (gasm *stmt)
 		&& REG_P (DECL_RTL (output_tvec[j]))
 		&& HARD_REGISTER_P (DECL_RTL (output_tvec[j]))
 		&& output_hregno == REGNO (DECL_RTL (output_tvec[j])))
-	      error ("invalid hard register usage between output operands");
+	      {
+		error ("invalid hard register usage between output operands");
+		error_seen = true;
+	      }
 
 	  /* Verify matching constraint operands use the same hard register
 	     and that the non-matching constraint operands do not use the same
@@ -3219,13 +3224,19 @@ expand_asm_stmt (gasm *stmt)
 		  }
 		if (i == match
 		    && output_hregno != input_hregno)
-		  error ("invalid hard register usage between output operand "
-			 "and matching constraint operand");
+		  {
+		    error ("invalid hard register usage between output "
+			   "operand and matching constraint operand");
+		    error_seen = true;
+		  }
 		else if (early_clobber_p
 			 && i != match
 			 && output_hregno == input_hregno)
-		  error ("invalid hard register usage between earlyclobber "
-			 "operand and input operand");
+		  {
+		    error ("invalid hard register usage between "
+			   "earlyclobber operand and input operand");
+		    error_seen = true;
+		  }
 	      }
 	}
 
@@ -3301,7 +3312,10 @@ expand_asm_stmt (gasm *stmt)
 	    op = validize_mem (op);
 
 	  if (! allows_reg && !MEM_P (op))
-	    error ("output number %d not directly addressable", i);
+	    {
+	      error ("output number %d not directly addressable", i);
+	      error_seen = true;
+	    }
 	  if ((! allows_mem && MEM_P (op) && GET_MODE (op) != BLKmode)
 	      || GET_CODE (op) == CONCAT)
 	    {
@@ -3341,6 +3355,19 @@ expand_asm_stmt (gasm *stmt)
 	inout_opnum.safe_push (i);
     }
 
+  const char *str = gimple_asm_string (stmt);
+  if (error_seen)
+    {
+      ninputs = 0;
+      noutputs = 0;
+      inout_opnum.truncate (0);
+      output_rvec.truncate (0);
+      clobber_rvec.truncate (0);
+      constraints.truncate (0);
+      CLEAR_HARD_REG_SET (clobbered_regs);
+      str = "";
+    }
+
   auto_vec<rtx, MAX_RECOG_OPERANDS> input_rvec;
   auto_vec<machine_mode, MAX_RECOG_OPERANDS> input_mode;
 
@@ -3399,7 +3426,7 @@ expand_asm_stmt (gasm *stmt)
     }
 
   /* For in-out operands, copy output rtx to input rtx.  */
-  unsigned ninout = inout_opnum.length();
+  unsigned ninout = inout_opnum.length ();
   for (i = 0; i < ninout; i++)
     {
       int j = inout_opnum[i];
@@ -3453,7 +3480,7 @@ expand_asm_stmt (gasm *stmt)
 
   rtx body = gen_rtx_ASM_OPERANDS ((noutputs == 0 ? VOIDmode
 				    : GET_MODE (output_rvec[0])),
-				   ggc_strdup (gimple_asm_string (stmt)),
+				   ggc_strdup (str),
 				   "", 0, argvec, constraintvec,
 				   labelvec, locus);
   MEM_VOLATILE_P (body) = gimple_asm_volatile_p (stmt);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index cce26b89cde..1b68c53b831 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -7081,9 +7081,14 @@ cxx_mark_addressable (tree exp, bool array_ref_p)
 	    && TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
 	    && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))))
 	  return true;
+	x = TREE_OPERAND (x, 0);
+	break;
+
+      case COMPONENT_REF:
+	if (bitfield_p (x))
+	  error ("attempt to take address of bit-field");
 	/* FALLTHRU */
       case ADDR_EXPR:
-      case COMPONENT_REF:
       case ARRAY_REF:
       case REALPART_EXPR:
       case IMAGPART_EXPR:
diff --git a/gcc/testsuite/c-c++-common/pr100785.c b/gcc/testsuite/c-c++-common/pr100785.c
new file mode 100644
index 00000000000..a3cd4cfa5c0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr100785.c
@@ -0,0 +1,21 @@
+/* PR inline-asm/100785 */
+
+struct S { int a : 1; };
+
+void
+foo (struct S *x)
+{
+  __asm__ ("" : "+m" (x->a));	/* { dg-error "address of bit-field" } */
+}				/* { dg-error "invalid lvalue in 'asm' output 0" "" { target c } .-1 } */
+				/* { dg-error "memory input 1 is not directly addressable" "" { target c } .-2 } */
+void
+bar (struct S *x)
+{
+  __asm__ ("" : "=m" (x->a));	/* { dg-error "address of bit-field" } */
+}				/* { dg-error "invalid lvalue in 'asm' output 0" "" { target c } .-1 } */
+
+void
+baz (struct S *x)
+{
+  __asm__ ("" : : "m" (x->a));	/* { dg-error "address of bit-field" } */
+}				/* { dg-error "memory input 0 is not directly addressable" "" { target c } .-1 } */


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-06-23 13:19 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-23 13:19 [gcc r11-8642] inline-asm: Fix ICE with bitfields in "m" operands [PR100785] Jakub Jelinek

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).