https://gcc.gnu.org/g:6547906bdbdb3feb0d3bd96e09ceffcbc489349f

commit r14-11554-g6547906bdbdb3feb0d3bd96e09ceffcbc489349f
Author: Jeff Law <j...@ventanamicro.com>
Date:   Mon Dec 30 13:51:55 2024 -0700

    [RISC-V][PR target/106544] Avoid ICEs due to bogus asms
    
    This is a fix for a bug Andrew P filed a while back where essentially a 
poorly
    crafted asm statement could trigger a ICE during assembly output.  Various
    cases will use INTVAL (op) without verifying the operand is a CONST_INT node
    first.
    
    The usual way to handle this is via output_operand_lossage, which this patch
    implements.
    
    I focused primarily on the CONST_INT cases, there could well be other 
problems
    in this space, if so they should get distinct bugs with testcases.
    
    Tested in my tester on rv32 and rv64.  Waiting for pre-commit testing before
    moving forward.
    
            PR target/106544
    gcc/
    
            * config/riscv/riscv.cc (riscv_print_operand): Issue an error for
            invalid operands rather than invalidly accessing INTVAL of an
            object that is not a CONST_INT.  Fix one error string for 'N'.
    
    gcc/testsuite
            * gcc.target/riscv/pr106544.c: New test.

Diff:
---
 gcc/config/riscv/riscv.cc                 | 151 +++++++++++++++++++-----------
 gcc/testsuite/gcc.target/riscv/pr106544.c |   6 ++
 2 files changed, 104 insertions(+), 53 deletions(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index a6a3b2745c53..584c3d52c5e7 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -6269,41 +6269,74 @@ riscv_print_operand (FILE *file, rtx op, int letter)
       fputs (GET_RTX_NAME (reverse_condition (code)), file);
       break;
 
-    case 'A': {
-      const enum memmodel model = memmodel_base (INTVAL (op));
-      if (riscv_memmodel_needs_amo_acquire (model)
-         && riscv_memmodel_needs_amo_release (model))
-       fputs (".aqrl", file);
-      else if (riscv_memmodel_needs_amo_acquire (model))
-       fputs (".aq", file);
-      else if (riscv_memmodel_needs_amo_release (model))
-       fputs (".rl", file);
+    case 'A':
+      if (!CONST_INT_P (op))
+       output_operand_lossage ("invalid operand for '%%%c'", letter);
+      else
+       {
+         const enum memmodel model = memmodel_base (INTVAL (op));
+         if (riscv_memmodel_needs_amo_acquire (model)
+             && riscv_memmodel_needs_amo_release (model))
+           fputs (".aqrl", file);
+         else if (riscv_memmodel_needs_amo_acquire (model))
+           fputs (".aq", file);
+         else if (riscv_memmodel_needs_amo_release (model))
+           fputs (".rl", file);
+       }
       break;
-    }
 
-    case 'I': {
-      const enum memmodel model = memmodel_base (INTVAL (op));
-      if (TARGET_ZTSO && model != MEMMODEL_SEQ_CST)
-       /* LR ops only have an annotation for SEQ_CST in the Ztso mapping.  */
-       break;
-      else if (model == MEMMODEL_SEQ_CST)
-       fputs (".aqrl", file);
-      else if (riscv_memmodel_needs_amo_acquire (model))
-       fputs (".aq", file);
+    case 'I':
+      if (!CONST_INT_P (op))
+       output_operand_lossage ("invalid operand for '%%%c'", letter);
+      else
+       {
+         const enum memmodel model = memmodel_base (INTVAL (op));
+         if (TARGET_ZTSO && model != MEMMODEL_SEQ_CST)
+           /* LR ops only have an annotation for SEQ_CST in the Ztso mapping.  
*/
+           break;
+         else if (model == MEMMODEL_SEQ_CST)
+           fputs (".aqrl", file);
+         else if (riscv_memmodel_needs_amo_acquire (model))
+           fputs (".aq", file);
+       }
       break;
-    }
 
-    case 'J': {
-      const enum memmodel model = memmodel_base (INTVAL (op));
-      if (TARGET_ZTSO && model == MEMMODEL_SEQ_CST)
-       /* SC ops only have an annotation for SEQ_CST in the Ztso mapping.  */
-       fputs (".rl", file);
-      else if (TARGET_ZTSO)
-       break;
-      else if (riscv_memmodel_needs_amo_release (model))
-       fputs (".rl", file);
+    case 'J':
+      if (!CONST_INT_P (op))
+       output_operand_lossage ("invalid operand for '%%%c'", letter);
+      else
+       {
+         const enum memmodel model = memmodel_base (INTVAL (op));
+         if (TARGET_ZTSO && model == MEMMODEL_SEQ_CST)
+           /* SC ops only have an annotation for SEQ_CST in the Ztso mapping.  
*/
+           fputs (".rl", file);
+         else if (TARGET_ZTSO)
+           break;
+         else if (riscv_memmodel_needs_amo_release (model))
+           fputs (".rl", file);
+       }
       break;
-    }
+
+    case 'L':
+      {
+       const char *ntl_hint = NULL;
+       switch (INTVAL (op))
+         {
+         case 0:
+           ntl_hint = "ntl.all";
+           break;
+         case 1:
+           ntl_hint = "ntl.pall";
+           break;
+         case 2:
+           ntl_hint = "ntl.p1";
+           break;
+         }
+
+      if (ntl_hint)
+       asm_fprintf (file, "%s\n\t", ntl_hint);
+      break;
+      }
 
     case 'i':
       if (code != REG)
@@ -6315,32 +6348,44 @@ riscv_print_operand (FILE *file, rtx op, int letter)
       break;
 
     case 'S':
-      {
-       rtx newop = GEN_INT (ctz_hwi (INTVAL (op)));
-       output_addr_const (file, newop);
-       break;
-      }
+      if (!CONST_INT_P (op))
+       output_operand_lossage ("invalid operand for '%%%c'", letter);
+      else
+       {
+         rtx newop = GEN_INT (ctz_hwi (INTVAL (op)));
+         output_addr_const (file, newop);
+       }
+      break;
     case 'T':
-      {
-       rtx newop = GEN_INT (ctz_hwi (~INTVAL (op)));
-       output_addr_const (file, newop);
-       break;
-      }
+      if (!CONST_INT_P (op))
+       output_operand_lossage ("invalid operand for '%%%c'", letter);
+      else
+       {
+         rtx newop = GEN_INT (ctz_hwi (~INTVAL (op)));
+         output_addr_const (file, newop);
+       }
+      break;
     case 'X':
-      {
-       int ival = INTVAL (op) + 1;
-       rtx newop = GEN_INT (ctz_hwi (ival) + 1);
-       output_addr_const (file, newop);
-       break;
-      }
+      if (!CONST_INT_P (op))
+       output_operand_lossage ("invalid operand for '%%%c'", letter);
+      else
+       {
+         int ival = INTVAL (op) + 1;
+         rtx newop = GEN_INT (ctz_hwi (ival) + 1);
+         output_addr_const (file, newop);
+       }
+      break;
     case 'Y':
-      {
-       unsigned int imm = (UINTVAL (op) & 63);
-       gcc_assert (imm <= 63);
-       rtx newop = GEN_INT (imm);
-       output_addr_const (file, newop);
-       break;
-      }
+      if (!CONST_INT_P (op))
+       output_operand_lossage ("invalid operand for '%%%c'", letter);
+      else
+       {
+         unsigned int imm = (UINTVAL (op) & 63);
+         gcc_assert (imm <= 63);
+         rtx newop = GEN_INT (imm);
+         output_addr_const (file, newop);
+       }
+      break;
     default:
       switch (code)
        {
diff --git a/gcc/testsuite/gcc.target/riscv/pr106544.c 
b/gcc/testsuite/gcc.target/riscv/pr106544.c
new file mode 100644
index 000000000000..6e449ee0c6b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr106544.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { *-*-* } { "-flto"} } */
+void f(int a)
+{
+  __asm("#%A0" : : "r"(a)); /* { dg-error "invalid 'asm': invalid operand" } */
+}

Reply via email to