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
cmd/compile: go1.21rc2: relocation R_X86_64_PC32 out of range error due to inliner changes #61218
Comments
Thanks for the report. The specific CL that your bisection points to does increase the amount of inlining, so it is not too surprising that the code generated by the Go compiler is getting bigger, especially if you make heavy use of closures. One thing that would be helpful here I think is if we had some understanding about just how much bigger your code is getting. If you could link your program with some special flags (as below) and then capture the size of the intermediates (both with the old Go version and with 1.21rc2, that would be great. Here is an example on how to gather the data (this uses a build of "himom.go", but hopefully you can do something along these lines for your program):
The "go.o" file is the output from the Go linker, prior to the point where it gets passed to the external linker. |
Hey @thanm, thank you for taking a look. I'm having a bit of trouble generating an archive or object file that's readable with the 'size' command. I first tried wrangling with our Bazel setup, but then moved on to a simpler go program and was still unsuccessful. I created a simple go program
$ cd project/other However I tried searching the docs in the go toolchain and the the closest thing I found was that |
The size program will work on an executable built from a main package. It won't work on the object file created by compiling a non-main package. If you follow @thanm 's script above you will get an object file in a temporary directory that |
Thank you for the help! With go1.20.5
With go1.21rc3
A small note for anyone in the future who may encounter something similar with Bazel. I added the -tmpdir option to gc_linkopts attr of the go_binary rule. |
Thanks for that. Looks like your text size is up considerably, 15% or so,but more importantly you are working with a binary that it is already enormous and very close to being in the "danger zone" with respect to relocations (from text to data) not reaching. I would suggest that you try to attack the problem from the angle of reducing the size of your generated code overall. In particular, in your generated code where you have functions that contain closures or return closures, e.g.
I would suggest changing your code generator to prefix these sorts of functions with "//go:noinline". This should (at least from what I can tell without being able to look at the complete source code) help restore the previous inliner behavior. Hope this helps. |
Thanks @thanm, Understood, we just wanted to report this issue in the case there was an increase in size out of the bounds the Go team was expecting. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Builds successfully on go version go1.20.4 linux/amd64 and go1.19.x Fails on go1.21rc2
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
In testing our code against go1.21rc2 we found that a large go_binary target (we use Bazel) fails to build only on go1.21rc2. git bisect points to this commit as the cause. The build time for this target also regresses significantly before the build exits compared to go1.20.4. Investigation details are posted in the last section of this ticket.
What did you expect to see?
Build pass. Program successfully builds.
What did you see instead?
We're not able to post a reproducible program here since the code is internal but we have investigation notes that we hope the Go team will find helpful.
To narrow down what code patterns might cause issues in go1.21rc2, we searched for build artifacts that got significantly larger between go1.20 vs go1.21rc2 and found some.
The generated packages are enormous but are built with generated code that follows a particular pattern that we believe does not interact well with go1.21rc2
The generated code makes extensive use of generics and anonymous function closures. Internally, we were able to rewrite the code generator to drop the use of generics and anonymous function closures and build the application successfully with go1.21rc2.
Unfortunately, we can’t share the exact code of the application but we can share the output of the code generator on a toy input before and after changes that allow the application to build on go1.21rc2.
Current go1.21rc2 failing toy generator output
Updated go1.21rc2 passing toy generator output
For the notable packages in the application, the symbol table dump is larger in go1.21c2 than in go1.20.
Trying to understand what new symbols might be generated in go1.21rc2, we picked a specific function name (e.g. _cffFallbackWithcff_100088_4) and searched for all instances in the symbol table of the archive in go1.20 and go1.21rc2.
The text was updated successfully, but these errors were encountered: