-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gccgo: type switch broken on AIX #39276
Comments
Thanks for the report. This is unfortunate. I guess we could restore the eqtype function on AIX. Is there some linker magic to make it merge the symbols? I agree that forcing -lgo doesn't seem nice. In theory there could be Go shared objects other than libgo itself, so forcing -lgo isn't a complete solution. |
Not that I'm aware of... |
There are some symbols that are nice to be merged, like compiler-generated wrapper functions, but the merging is not required for correctness, as we don't compare addresses of them. Type descriptors are probably the only one. |
Change https://golang.org/cl/235697 mentions this issue: |
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
I've discovered that there is another place where It can be reproduced with
The current gimple representation for
It should be something like
Ps: The issue is already closed but that the exact same bug, thus I comment there. Tell me if I need to open another issue. |
You can pass in the |
Change https://golang.org/cl/255202 mentions this issue: |
I've checked quickly, but it doesn't seem to have anywhere else in the compiler that need to call runtime.eqtype. However, As a workaround, I've changed this assertion to use the hash parameter |
You should be able to compare |
All type switch clauses must call runtime.eqtype if the linker isn't able to merge type descriptors pointers. Previously, only interface-type clauses were doing it. Updates golang/go#39276 Change-Id: Ic06d95081e837122c409a2aba377d1afae676342 Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/255202 Reviewed-by: Cherry Zhang <cherryyz@google.com> Reviewed-by: Ian Lance Taylor <iant@golang.org> Trust: Cherry Zhang <cherryyz@google.com>
Using First, how the equality operation is made between strings ? Because if I remember correctly, some constant strings can be associated to a Read-Only symbol (or at least an address in RO sections). Thus, checking that two pointers are equal would be faster that checking if the whole strings are equal. If it's indeed how it's performed, we would have the same problem than with types, these symbols won't be merged. Moreover, I was able to fix type equalities in Edit: Actually, the previous example is failing because the two |
I don't think there is a problem with strings. For strings we never assume that if the pointers are not equal that the strings are not equal. The library assumes that types are canonicalized (there is only instance of a given type) but that is not true for strings (there can be multiple instances of a particular string). In the reflect package, we used to have a canonicalization map that ensured that when the program sees a (This of course assumes that there is only a single version of the canonicalization map in the program, which for AIX may mean that there is only a single version of the reflect package in the program. I don't know how AIX handles that kind of thing when shared libraries are involved.) |
No, it won't happen. Only the reflect tests might be a bit problematic as gotests is duplicating it. I'll check that anywya. |
Change https://golang.org/cl/260158 mentions this issue: |
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 (cherry picked from commit f4b9b13)
I'm trying to build and test gccgo provided by gcc-10. But I've discovered that type-switch aren't working anymore on AIX, in some cases.
This occurs because of a type duplication between the Go program and the libgo (shared not with
--static-libgo
). On Linux, AFAIK the linker and the loader are able to merge symbols being the same across .o/.so and thus will merge type symbols if there are identical. On AIX, this merge doesn't occur. Thus, this can result of having two identical type symbols.For example, I'm using this testcase:
With Go Toolchain and gccgo-9, the result was "fmt.Stringer main.Animal". With gccgo-10, the result is "main.Stringer main.Animal". That's because the type symbol of Animal.String() result isn't the same of the one expected by fmt.Stringer interface.
When using gdb and stopping at https://github.com/golang/gofrontend/blob/master/libgo/go/runtime/iface.go#L487, we have the following values ($r9 being
toMethod.typ
and $r10fromMethod.mtyp
, or the opposite but it doesn't really matter there)As you can see, these two type symbols are identical. But as there are two different pointers, the current code won't accept them.
This problem is triggered by https://go-review.googlesource.com/c/gofrontend/+/179598 and https://go-review.googlesource.com/c/gofrontend/+/182978. In fact, only the part about eqtype is problematic, because even if gccgo is generating unique type descriptors, on AIX the duplication can still occur.
I know that I'm discovering this really late. But would it be possible to keep eqtype function for AIX ? I've tried locally and it's working. The final solution would be to have this symbol merging happening also on AIX. But AFAIK it's not possible for now.
Another solution which we were using during gcc-7 and gcc-8, is to add -lgo before Go object files is also working (AIX linker is able to do the merge in this case). But the patch we have for that is too intrusive to be merged inside gcc tree (there are forcing -lgo in gcc.c), so I'd rather sticking to the first solution.
/cc @ianlancetaylor @cherrymui
The text was updated successfully, but these errors were encountered: