aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorClément Chigot <chigot.c@gmail.com>2020-05-29 11:39:42 +0200
committerIan Lance Taylor <iant@golang.org>2020-08-10 16:45:16 -0700
commitf4b9b136808c31118c52c0addafb3fd323484d1b (patch)
treecc518ef3fc753c719afdcd1c2eb5476188f3c027 /libgo
parent636686662326496f68451e7eb91882fe462f850a (diff)
downloadgcc-f4b9b136808c31118c52c0addafb3fd323484d1b.zip
gcc-f4b9b136808c31118c52c0addafb3fd323484d1b.tar.gz
gcc-f4b9b136808c31118c52c0addafb3fd323484d1b.tar.bz2
runtime: revert eqtype for AIX
AIX linker is not able to merge identical type descriptors in a single symbol if there are coming from different object or shared object files. This results into several pointers referencing the same type descriptors. Thus, eqtype is needed to ensure that these different symbols will be considered as the same type descriptor. Fixes golang/go#39276 gcc/go/ChangeLog: * go-c.h (struct go_create_gogo_args): Add need_eqtype field. * go-lang.c (go_langhook_init): Set need_eqtype. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/235697
Diffstat (limited to 'libgo')
-rw-r--r--libgo/go/runtime/alg.go10
-rw-r--r--libgo/go/runtime/eqtype.go21
-rw-r--r--libgo/go/runtime/eqtype_aix_gccgo.go32
-rw-r--r--libgo/go/runtime/iface.go12
4 files changed, 64 insertions, 11 deletions
diff --git a/libgo/go/runtime/alg.go b/libgo/go/runtime/alg.go
index 95f02aa..b5b22cf 100644
--- a/libgo/go/runtime/alg.go
+++ b/libgo/go/runtime/alg.go
@@ -276,7 +276,7 @@ func nilinterequal(p, q unsafe.Pointer) bool {
}
func efaceeq(x, y eface) bool {
t := x._type
- if t != y._type {
+ if !eqtype(t, y._type) {
return false
}
if t == nil {
@@ -301,7 +301,7 @@ func ifaceeq(x, y iface) bool {
return false
}
t := *(**_type)(xtab)
- if t != *(**_type)(y.tab) {
+ if !eqtype(t, *(**_type)(y.tab)) {
return false
}
eq := t.equal
@@ -322,7 +322,7 @@ func ifacevaleq(x iface, t *_type, p unsafe.Pointer) bool {
return false
}
xt := *(**_type)(x.tab)
- if xt != t {
+ if !eqtype(xt, t) {
return false
}
eq := t.equal
@@ -343,7 +343,7 @@ func ifaceefaceeq(x iface, y eface) bool {
return false
}
xt := *(**_type)(x.tab)
- if xt != y._type {
+ if !eqtype(xt, y._type) {
return false
}
eq := xt.equal
@@ -360,7 +360,7 @@ func efacevaleq(x eface, t *_type, p unsafe.Pointer) bool {
if x._type == nil {
return false
}
- if x._type != t {
+ if !eqtype(x._type, t) {
return false
}
eq := t.equal
diff --git a/libgo/go/runtime/eqtype.go b/libgo/go/runtime/eqtype.go
new file mode 100644
index 0000000..71d64ee
--- /dev/null
+++ b/libgo/go/runtime/eqtype.go
@@ -0,0 +1,21 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !aix,gccgo
+
+package runtime
+
+import (
+ _ "unsafe"
+)
+
+// go:linkname is required as eqtype is a compiler-called
+// function on some OSes.
+//
+//go:linkname eqtype
+
+// Return whether two type descriptors are equal.
+func eqtype(t1, t2 *_type) bool {
+ return t1 == t2
+}
diff --git a/libgo/go/runtime/eqtype_aix_gccgo.go b/libgo/go/runtime/eqtype_aix_gccgo.go
new file mode 100644
index 0000000..6d32022
--- /dev/null
+++ b/libgo/go/runtime/eqtype_aix_gccgo.go
@@ -0,0 +1,32 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build aix,gccgo
+
+package runtime
+
+import (
+ _ "unsafe"
+)
+
+// eqtype is a compiler-called function.
+//
+//go:linkname eqtype
+
+// Return whether two type descriptors are equal.
+// This is gccgo-specific, as some linkers are not able
+// to merge identical type descriptors coming from
+// different object or shared object files.
+func eqtype(t1, t2 *_type) bool {
+ switch {
+ case t1 == t2:
+ return true
+ case t1 == nil || t2 == nil:
+ return false
+ case t1.kind != t2.kind || t1.hash != t2.hash:
+ return false
+ default:
+ return t1.string() == t2.string()
+ }
+}
diff --git a/libgo/go/runtime/iface.go b/libgo/go/runtime/iface.go
index 877e191..5667ddb 100644
--- a/libgo/go/runtime/iface.go
+++ b/libgo/go/runtime/iface.go
@@ -232,7 +232,7 @@ func (m *itab) init() string {
ri++
}
- if lhsMethod.typ != rhsMethod.mtyp {
+ if !eqtype(lhsMethod.typ, rhsMethod.mtyp) {
m.methods[1] = nil
return *lhsMethod.name
}
@@ -406,7 +406,7 @@ func ifaceI2I2(inter *_type, i iface) (iface, bool) {
// Convert an empty interface to a pointer non-interface type.
func ifaceE2T2P(t *_type, e eface) (unsafe.Pointer, bool) {
- if t != e._type {
+ if !eqtype(t, e._type) {
return nil, false
} else {
return e.data, true
@@ -415,7 +415,7 @@ func ifaceE2T2P(t *_type, e eface) (unsafe.Pointer, bool) {
// Convert a non-empty interface to a pointer non-interface type.
func ifaceI2T2P(t *_type, i iface) (unsafe.Pointer, bool) {
- if i.tab == nil || t != *(**_type)(i.tab) {
+ if i.tab == nil || !eqtype(t, *(**_type)(i.tab)) {
return nil, false
} else {
return i.data, true
@@ -424,7 +424,7 @@ func ifaceI2T2P(t *_type, i iface) (unsafe.Pointer, bool) {
// Convert an empty interface to a non-pointer non-interface type.
func ifaceE2T2(t *_type, e eface, ret unsafe.Pointer) bool {
- if t != e._type {
+ if !eqtype(t, e._type) {
typedmemclr(t, ret)
return false
} else {
@@ -439,7 +439,7 @@ func ifaceE2T2(t *_type, e eface, ret unsafe.Pointer) bool {
// Convert a non-empty interface to a non-pointer non-interface type.
func ifaceI2T2(t *_type, i iface, ret unsafe.Pointer) bool {
- if i.tab == nil || t != *(**_type)(i.tab) {
+ if i.tab == nil || !eqtype(t, *(**_type)(i.tab)) {
typedmemclr(t, ret)
return false
} else {
@@ -485,7 +485,7 @@ func ifaceT2Ip(to, from *_type) bool {
ri++
}
- if fromMethod.mtyp != toMethod.typ {
+ if !eqtype(fromMethod.mtyp, toMethod.typ) {
return false
}