diff mbox

Go patch committed: check backend alignment for memequalNN functions

Message ID CAOyqgcX1Z0zdBidA2s7v0XfRHJrL6AhB08e1peERY0u7iHxf7g@mail.gmail.com
State New
Headers show

Commit Message

Ian Lance Taylor March 22, 2017, 1:59 p.m. UTC
The Go frontend was assuming the usual required alignment for the
memequalNN functions (16 bits for int16, 32 for int32, etc.). However,
on m68k the required alignment of int32 is only 16 bits. Assuming the
memequalNN alignment caused the compiler to incorrectly decide that
int32 required a specially generated function rather than calling
memequal32. This then crashed if the type descriptor were generated
after type-specific functions had been written.

Bootstrapped and ran Go tests on x86_64-pc-linux-gnu.  Committed to mainline.

This fixes GCC PR 80128.

Ian
diff mbox

Patch

Index: gcc/go/gofrontend/types.h
===================================================================
--- gcc/go/gofrontend/types.h	(revision 245745)
+++ gcc/go/gofrontend/types.h	(working copy)
@@ -993,6 +993,9 @@  class Type
 				const std::string& equal_name,
 				Function_type* equal_fntype);
 
+  // Return the alignment required by the memequalN function.
+  static int64_t memequal_align(Gogo*, int size);
+
   // Export the type.
   void
   export_type(Export* exp) const
Index: gcc/go/gofrontend/types.cc
===================================================================
--- gcc/go/gofrontend/types.cc	(revision 245745)
+++ gcc/go/gofrontend/types.cc	(working copy)
@@ -1580,6 +1580,42 @@  Type::make_type_descriptor_ptr_type()
   return ret;
 }
 
+// Return the alignment required by the memequalN function.  N is a
+// type size: 16, 32, 64, or 128.  The memequalN functions are defined
+// in libgo/go/runtime/alg.go.
+
+int64_t
+Type::memequal_align(Gogo* gogo, int size)
+{
+  const char* tn;
+  switch (size)
+    {
+    case 16:
+      tn = "int16";
+      break;
+    case 32:
+      tn = "int32";
+      break;
+    case 64:
+      tn = "int64";
+      break;
+    case 128:
+      // The code uses [2]int64, which must have the same alignment as
+      // int64.
+      tn = "int64";
+      break;
+    default:
+      go_unreachable();
+    }
+
+  Type* t = Type::lookup_integer_type(tn);
+
+  int64_t ret;
+  if (!t->backend_type_align(gogo, &ret))
+    go_unreachable();
+  return ret;
+}
+
 // Return whether this type needs specially built type functions.
 // This returns true for types that are comparable and either can not
 // use an identity comparison, or are a non-standard size.
@@ -1614,14 +1650,13 @@  Type::needs_specific_type_functions(Gogo
     case 0:
     case 1:
     case 2:
-      return align < 2;
+      return align < Type::memequal_align(gogo, 16);
     case 4:
-      return align < 4;
+      return align < Type::memequal_align(gogo, 32);
     case 8:
-      return align < 8;
+      return align < Type::memequal_align(gogo, 64);
     case 16:
-      // 8, not 16, because of how runtime.memequal128 is written.
-      return align < 8;
+      return align < Type::memequal_align(gogo, 128);
     default:
       return true;
     }
@@ -1713,7 +1748,7 @@  Type::type_functions(Gogo* gogo, Named_t
 	  equal_fnname = "runtime.memequal8";
 	  break;
 	case 2:
-	  if (align < 2)
+	  if (align < Type::memequal_align(gogo, 16))
 	    build_functions = true;
 	  else
 	    {
@@ -1722,7 +1757,7 @@  Type::type_functions(Gogo* gogo, Named_t
 	    }
 	  break;
 	case 4:
-	  if (align < 4)
+	  if (align < Type::memequal_align(gogo, 32))
 	    build_functions = true;
 	  else
 	    {
@@ -1731,7 +1766,7 @@  Type::type_functions(Gogo* gogo, Named_t
 	    }
 	  break;
 	case 8:
-	  if (align < 8)
+	  if (align < Type::memequal_align(gogo, 64))
 	    build_functions = true;
 	  else
 	    {
@@ -1740,8 +1775,7 @@  Type::type_functions(Gogo* gogo, Named_t
 	    }
 	  break;
 	case 16:
-	  // 8, not 16, because of how runtime.memequal128 is written.
-	  if (align < 8)
+	  if (align < Type::memequal_align(gogo, 128))
 	    build_functions = true;
 	  else
 	    {