aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2017-03-22 13:59:01 +0000
committerIan Lance Taylor <iant@google.com>2017-03-22 13:59:01 +0000
commita2b3ce91b5734fd46e5e18d93c727ca87d66eca4 (patch)
tree568a77579df80547be833b5a4d72b2c9628a1fea
parentdb6d55fa25600d3bb47a219a6e04708bd3186112 (diff)
PR go/80128
compiler: check backend alignment for memequalNN functions The code 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. Fixes GCC PR 80128. Reviewed-on: https://go-review.googlesource.com/38433 git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@246382 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/go/gofrontend/types.cc54
-rw-r--r--gcc/go/gofrontend/types.h3
2 files changed, 47 insertions, 10 deletions
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 9423ef63276..f65dbd73c33 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -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* 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_type* name, Function_type* hash_fntype,
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_type* name, Function_type* hash_fntype,
}
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_type* name, Function_type* hash_fntype,
}
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_type* name, Function_type* hash_fntype,
}
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
{
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index a2a6e611cc8..47a70fcd08f 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -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