diff options
author | Clément Chigot <chigot.c@gmail.com> | 2020-05-29 11:39:42 +0200 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-08-10 16:45:16 -0700 |
commit | f4b9b136808c31118c52c0addafb3fd323484d1b (patch) | |
tree | cc518ef3fc753c719afdcd1c2eb5476188f3c027 /libgo | |
parent | 636686662326496f68451e7eb91882fe462f850a (diff) | |
download | gcc-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.go | 10 | ||||
-rw-r--r-- | libgo/go/runtime/eqtype.go | 21 | ||||
-rw-r--r-- | libgo/go/runtime/eqtype_aix_gccgo.go | 32 | ||||
-rw-r--r-- | libgo/go/runtime/iface.go | 12 |
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 } |