diff mbox series

[committed,PR,target/13721] Emit reasonable diagnostic rather than ICE for bogus ASM on H8 port

Message ID 81fd4c8f34737fe1e0212315a3140ed48902e0d8.camel@redhat.com
State New
Headers show
Series [committed,PR,target/13721] Emit reasonable diagnostic rather than ICE for bogus ASM on H8 port | expand

Commit Message

Jeff Law Jan. 24, 2020, 4:07 p.m. UTC
This fixes a long standing minor issue with the H8 port.  Again, given
the very narrow scope here, I'm going forward even though we're in
stage4.

The H8 port will ICE under the right (wrong?) circumstances when we get
an unexpected operand in an asm, particularly asms that want to output
the name of a byte sized register.

Eons ago this was a segfault.  Kazu improved things with an assertion,
but really the right thing to do here is to use output_operand_lossage.

This patch protects the calls to byte_reg, ensuring it's only called
with REGs and adds calls to output_operand_lossage for the other cases.

Tested in my tester overnight with no regressions.  Committed to the
trunk.

Jeff
commit 64c9f2d9972ad359a32f0a97ee0a806c2532db15
Author: Jeff Law <law@redhat.com>
Date:   Fri Jan 24 08:57:46 2020 -0700

    Emit reasonable diagnostic rather than ICE on invalid ASM on H8 port
    
            PR target/13721
            * config/h8300/h8300.c (h8300_print_operand): Only call byte_reg
            for REGs.  Call output_operand_lossage to get more reasonable
            diagnostics.
    
            PR target/13721
            * gcc.target/h8300/pr13721.c: New test.
diff mbox series

Patch

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 27e5ec23409..4d851c0b170 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@ 
+2020-01-24  Jeff Law  <law@redhat.com>
+
+	PR target/13721
+	* config/h8300/h8300.c (h8300_print_operand): Only call byte_reg
+	for REGs.  Call output_operand_lossage to get more reasonable
+	diagnostics.
+
 2020-01-24  Andrew Stubbs  <ams@codesourcery.com>
 
 	* config/gcn/gcn-valu.md (vec_cmp<mode>di): Use
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index ffbfa9eaaa9..def8be344af 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -1647,40 +1647,52 @@  h8300_print_operand (FILE *file, rtx x, int code)
     case 's':
       if (GET_CODE (x) == CONST_INT)
 	fprintf (file, "#%ld", (INTVAL (x)) & 0xff);
-      else
+      else if (GET_CODE (x) == REG)
 	fprintf (file, "%s", byte_reg (x, 0));
+      else
+	output_operand_lossage ("Expected register or constant integer.");
       break;
     case 't':
       if (GET_CODE (x) == CONST_INT)
 	fprintf (file, "#%ld", (INTVAL (x) >> 8) & 0xff);
-      else
+      else if (GET_CODE (x) == REG)
 	fprintf (file, "%s", byte_reg (x, 1));
+      else
+	output_operand_lossage ("Expected register or constant integer.");
       break;
     case 'w':
       if (GET_CODE (x) == CONST_INT)
 	fprintf (file, "#%ld", INTVAL (x) & 0xff);
-      else
+      else if (GET_CODE (x) == REG)
 	fprintf (file, "%s",
 		 byte_reg (x, TARGET_H8300 ? 2 : 0));
+      else
+	output_operand_lossage ("Expected register or constant integer.");
       break;
     case 'x':
       if (GET_CODE (x) == CONST_INT)
 	fprintf (file, "#%ld", (INTVAL (x) >> 8) & 0xff);
-      else
+      else if (GET_CODE (x) == REG)
 	fprintf (file, "%s",
 		 byte_reg (x, TARGET_H8300 ? 3 : 1));
+      else
+	output_operand_lossage ("Expected register or constant integer.");
       break;
     case 'y':
       if (GET_CODE (x) == CONST_INT)
 	fprintf (file, "#%ld", (INTVAL (x) >> 16) & 0xff);
-      else
+      else if (GET_CODE (x) == REG)
 	fprintf (file, "%s", byte_reg (x, 0));
+      else
+	output_operand_lossage ("Expected register or constant integer.");
       break;
     case 'z':
       if (GET_CODE (x) == CONST_INT)
 	fprintf (file, "#%ld", (INTVAL (x) >> 24) & 0xff);
-      else
+      else if (GET_CODE (x) == REG)
 	fprintf (file, "%s", byte_reg (x, 1));
+      else
+	output_operand_lossage ("Expected register or constant integer.");
       break;
 
     default:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c465ff99541..c0699907f1c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@ 
+2020-01-24  Jeff Law  <law@redhat.com
+
+	PR target/13721
+	* gcc.target/h8300/pr13721.c: New test.
+
 2020-01-24  Christophe Lyon  <christophe.lyon@linaro.org>
 
 	PR debug/92763
diff --git a/gcc/testsuite/gcc.target/h8300/pr13721.c b/gcc/testsuite/gcc.target/h8300/pr13721.c
new file mode 100644
index 00000000000..817b5377448
--- /dev/null
+++ b/gcc/testsuite/gcc.target/h8300/pr13721.c
@@ -0,0 +1,71 @@ 
+static __inline__ __attribute__((always_inline)) void set_bit(int nr, volatile void * addr) 
+{
+	volatile unsigned char *b_addr;
+	b_addr = (volatile unsigned char *)addr + ((nr >> 3) ^ 3);
+	nr &= 7;
+	if (__builtin_constant_p (nr))					  
+	{								  
+		switch(nr)						  
+		{							  
+		case 0:							  
+			__asm__("bset #0,%0" :"+m"(*b_addr) :"m"(*b_addr));
+			break;	     					  
+		case 1:		     					  
+			__asm__("bset #1,%0" :"+m"(*b_addr) :"m"(*b_addr));
+			break;	     					  
+		case 2:		     					  
+			__asm__("bset #2,%0" :"+m"(*b_addr) :"m"(*b_addr));
+			break;	     					  
+		case 3:		     					  
+			__asm__("bset #3,%0" :"+m"(*b_addr) :"m"(*b_addr));
+			break;	     					  
+		case 4:		     					  
+			__asm__("bset #4,%0" :"+m"(*b_addr) :"m"(*b_addr));
+			break;	     					  
+		case 5:		     					  
+			__asm__("bset #5,%0" :"+m"(*b_addr) :"m"(*b_addr));
+			break;	     					  
+		case 6:		     					  
+			__asm__("bset #6,%0" :"+m"(*b_addr) :"m"(*b_addr));
+			break;	     					  
+		case 7:		     					  
+			__asm__("bset #7,%0" :"+m"(*b_addr) :"m"(*b_addr));
+			break;						  
+		}							  
+	}								  
+	else								  
+	{								  
+		__asm__("bset %w1,%0"  :"+m"(*b_addr)  :"g"(nr),"m"(*b_addr));	/* { dg-error "invalid 'asm'" "" } */
+
+	}								  
+}
+
+static __inline__ __attribute__((always_inline)) int test_bit(int nr, const volatile void * addr)
+{
+	return (*((volatile unsigned char *)addr + ((nr >> 3) ^ 3)) & (1UL << (nr & 7))) != 0;
+}
+
+struct a {
+        unsigned long a;
+};
+
+void dummy(struct a *a, int b);
+
+int ice_func(struct a *a, int b)
+{
+  int c,d;
+  unsigned int e;
+
+  for(c=0;c<b;c++) {
+    for(d=b; d <= b; d++) {
+      if (!test_bit(d, &e)) {
+        dummy(a, d * a->a);
+        dummy(a, d * a->a);
+        set_bit(d, &e);
+      }
+    }
+    dummy(a, d * a->a);
+  }
+
+  return 0;
+}