-
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
cmd/compile: ICE at composite literal assignment with alignment > PtrSize #54638
Comments
Change https://go.dev/cl/425256 mentions this issue: |
We could raise the alignment of stack frames to 8 bytes. Callbacks from assembly might make that difficult, especially if we're still on abi0 though... |
Yeah, increase stack alignment is a possibility, and as you said assembly code may be tricky. (There are probably some discussions about increasing stack alignment in the past.) |
I can reproduce the same on linux/arm with Go 1.19 |
@gopherbot please backport this to Go 1.19. This may cause compiler crash on valid real programs. Thanks. |
Backport issue(s) opened: #54697 (for 1.19). Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://go.dev/wiki/MinorReleases. |
Change https://go.dev/cl/425935 mentions this issue: |
…arger than PtrSize In typebits.Set we check that the offset is a multiple of the alignment, which makes perfect sense. But for values like atomic.Int64, which has 8-byte alignment even on 32-bit platforms (i.e. the alignment is larger than PtrSize), if it is on stack it may be under-aligned, as the stack frame is only PtrSize aligned. Normally we would prevent such values on stack, as the escape analysis force values with higher alignment to heap. But for a composite literal assignment like x = AlignedType{...}, the compiler creates an autotmp for the RHS then copies it to the LHS. The autotmp is on stack and may be under-aligned. Currently this may cause an ICE in the typebits.Set check. This CL makes it align the _offset_ of the autotmp to 8 bytes, which satisfies the check. Note that this is actually lying: the actual address at run time may not necessarily be 8-byte aligned as we only align SP to 4 bytes. The under-alignment is probably okay. The only purpose for the autotmp is to copy the value to the LHS, and the copying code we generate (at least currently) doesn't care the alignment beyond stack alignment. Updates #54638. Fixes #54697. Change-Id: I13c16afde2eea017479ff11dfc24092bcb8aba6a Reviewed-on: https://go-review.googlesource.com/c/go/+/425256 Run-TryBot: Cherry Mui <cherryyz@google.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: David Chase <drchase@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> (cherry picked from commit 1211a62) Reviewed-on: https://go-review.googlesource.com/c/go/+/425935
In typebits.Set we check that the offset is a multiple of the alignment, which makes perfect sense. But for values like atomic.Int64, which has 8-byte alignment even on 32-bit platforms (i.e. the alignment is larger than PtrSize), if it is on stack it may be under-aligned, as the stack frame is only PtrSize aligned. Normally we would prevent such values on stack, as the escape analysis force values with higher alignment to heap. But for a composite literal assignment like x = AlignedType{...}, the compiler creates an autotmp for the RHS then copies it to the LHS. The autotmp is on stack and may be under-aligned. Currently this may cause an ICE in the typebits.Set check. This CL makes it align the _offset_ of the autotmp to 8 bytes, which satisfies the check. Note that this is actually lying: the actual address at run time may not necessarily be 8-byte aligned as we only align SP to 4 bytes. The under-alignment is probably okay. The only purpose for the autotmp is to copy the value to the LHS, and the copying code we generate (at least currently) doesn't care the alignment beyond stack alignment. Fixes golang#54638. Change-Id: I13c16afde2eea017479ff11dfc24092bcb8aba6a Reviewed-on: https://go-review.googlesource.com/c/go/+/425256 Run-TryBot: Cherry Mui <cherryyz@google.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: David Chase <drchase@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
…arger than PtrSize In typebits.Set we check that the offset is a multiple of the alignment, which makes perfect sense. But for values like atomic.Int64, which has 8-byte alignment even on 32-bit platforms (i.e. the alignment is larger than PtrSize), if it is on stack it may be under-aligned, as the stack frame is only PtrSize aligned. Normally we would prevent such values on stack, as the escape analysis force values with higher alignment to heap. But for a composite literal assignment like x = AlignedType{...}, the compiler creates an autotmp for the RHS then copies it to the LHS. The autotmp is on stack and may be under-aligned. Currently this may cause an ICE in the typebits.Set check. This CL makes it align the _offset_ of the autotmp to 8 bytes, which satisfies the check. Note that this is actually lying: the actual address at run time may not necessarily be 8-byte aligned as we only align SP to 4 bytes. The under-alignment is probably okay. The only purpose for the autotmp is to copy the value to the LHS, and the copying code we generate (at least currently) doesn't care the alignment beyond stack alignment. Updates golang#54638. Fixes golang#54697. Change-Id: I13c16afde2eea017479ff11dfc24092bcb8aba6a Reviewed-on: https://go-review.googlesource.com/c/go/+/425256 Run-TryBot: Cherry Mui <cherryyz@google.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: David Chase <drchase@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> (cherry picked from commit 1211a62) Reviewed-on: https://go-review.googlesource.com/c/go/+/425935
What version of Go are you using (
go version
)?tip (60ad3c4)
Does this issue reproduce with the latest release?
Unsure. It doesn't immediately reproduce with Go 1.19, but based on the code I think it might be possible.
What operating system and processor architecture are you using (
go env
)?Building for linux/arm.
What did you do?
Build this code for ARM
$ GOARCH=arm GOOS=linux go build s.go
.What did you expect to see?
Build successfully.
What did you see instead?
ICE.
Here, we have a local variable
srv
of typehttp.Server
, which contains async.WaitGroup
which in turn contains aatomic.Uint64
, which makes it 8-byte aligned even on 32-bit platforms.The compiler already force variables with alignment larger than the stack alignment (PtrSize) to heap. But here for the composite literal assignment the compiler generates an autotmp
That autotmp lives on stack, and doesn't have 8-byte alignment. This triggers an assertion when emitting the stack maps https://cs.opensource.google/go/go/+/master:src/cmd/compile/internal/typebits/typebits.go;l=17
I think it is probably okay to have an under-aligned autotmp on stack. The only purpose for the autotmp is to copy the value to the LHS, and the copying code we generate (at least currently) doesn't care the alignment beyond stack alignment. So maybe we can relax the check to allow under-aligned values on stack? (It would be good to check that it is only used for copying and doesn't need the alignment beyond PtrSize, but I'm not sure how to.)
Not sure if there is a better fix. Not using such autotmp would need much more work.
We could align the offset of the autotmp to 8 bytes, which would satisfy the check. But it is just faking. The actual address at run time may not necessarily be 8-byte aligned.
The text was updated successfully, but these errors were encountered: