mirror of
https://github.com/golang/go
synced 2024-10-02 22:25:08 +00:00
cmd/compile/internal/typebits: relax alignment check
Now we have 8-byte alignment types on 32-bit system, so in some rare case, e.g, generated wrapper for embedded interface, the function argument may need more than 4 byte alignment. We could pad somehow, but this is a rare case which makes it hard to ensure that we've got it right. So relaxing the check for argument and return value region of the stack. Fixes #54991 Change-Id: I34986e17a920254392a39439ad3dcb323da2ea8d Reviewed-on: https://go-review.googlesource.com/c/go/+/431098 Reviewed-by: Keith Randall <khr@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com> Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com> Auto-Submit: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
parent
638c9aad5f
commit
00bee6d9a4
|
@ -425,7 +425,7 @@ func (lv *liveness) pointerMap(liveout bitvec.BitVec, vars []*ir.Name, args, loc
|
||||||
if node.FrameOffset() < 0 {
|
if node.FrameOffset() < 0 {
|
||||||
lv.f.Fatalf("Node %v has frameoffset %d\n", node.Sym().Name, node.FrameOffset())
|
lv.f.Fatalf("Node %v has frameoffset %d\n", node.Sym().Name, node.FrameOffset())
|
||||||
}
|
}
|
||||||
typebits.Set(node.Type(), node.FrameOffset(), args)
|
typebits.SetNoCheck(node.Type(), node.FrameOffset(), args)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
fallthrough // PPARAMOUT in registers acts memory-allocates like an AUTO
|
fallthrough // PPARAMOUT in registers acts memory-allocates like an AUTO
|
||||||
|
@ -1498,7 +1498,7 @@ func WriteFuncMap(fn *ir.Func, abiInfo *abi.ABIParamResultInfo) {
|
||||||
bv := bitvec.New(int32(nptr) * 2)
|
bv := bitvec.New(int32(nptr) * 2)
|
||||||
|
|
||||||
for _, p := range abiInfo.InParams() {
|
for _, p := range abiInfo.InParams() {
|
||||||
typebits.Set(p.Type, p.FrameOffset(abiInfo), bv)
|
typebits.SetNoCheck(p.Type, p.FrameOffset(abiInfo), bv)
|
||||||
}
|
}
|
||||||
|
|
||||||
nbitmap := 1
|
nbitmap := 1
|
||||||
|
@ -1513,7 +1513,7 @@ func WriteFuncMap(fn *ir.Func, abiInfo *abi.ABIParamResultInfo) {
|
||||||
if fn.Type().NumResults() > 0 {
|
if fn.Type().NumResults() > 0 {
|
||||||
for _, p := range abiInfo.OutParams() {
|
for _, p := range abiInfo.OutParams() {
|
||||||
if len(p.Registers) == 0 {
|
if len(p.Registers) == 0 {
|
||||||
typebits.Set(p.Type, p.FrameOffset(abiInfo), bv)
|
typebits.SetNoCheck(p.Type, p.FrameOffset(abiInfo), bv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
off = objw.BitVec(lsym, off, bv)
|
off = objw.BitVec(lsym, off, bv)
|
||||||
|
|
|
@ -14,7 +14,16 @@ import (
|
||||||
// the first run and then simply copied into bv at the correct offset
|
// the first run and then simply copied into bv at the correct offset
|
||||||
// on future calls with the same type t.
|
// on future calls with the same type t.
|
||||||
func Set(t *types.Type, off int64, bv bitvec.BitVec) {
|
func Set(t *types.Type, off int64, bv bitvec.BitVec) {
|
||||||
if uint8(t.Alignment()) > 0 && off&int64(uint8(t.Alignment())-1) != 0 {
|
set(t, off, bv, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNoCheck is like Set, but do not check for alignment.
|
||||||
|
func SetNoCheck(t *types.Type, off int64, bv bitvec.BitVec) {
|
||||||
|
set(t, off, bv, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func set(t *types.Type, off int64, bv bitvec.BitVec, skip bool) {
|
||||||
|
if !skip && uint8(t.Alignment()) > 0 && off&int64(uint8(t.Alignment())-1) != 0 {
|
||||||
base.Fatalf("typebits.Set: invalid initial alignment: type %v has alignment %d, but offset is %v", t, uint8(t.Alignment()), off)
|
base.Fatalf("typebits.Set: invalid initial alignment: type %v has alignment %d, but offset is %v", t, uint8(t.Alignment()), off)
|
||||||
}
|
}
|
||||||
if !t.HasPointers() {
|
if !t.HasPointers() {
|
||||||
|
@ -72,13 +81,13 @@ func Set(t *types.Type, off int64, bv bitvec.BitVec) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
for i := int64(0); i < t.NumElem(); i++ {
|
for i := int64(0); i < t.NumElem(); i++ {
|
||||||
Set(elt, off, bv)
|
set(elt, off, bv, skip)
|
||||||
off += elt.Size()
|
off += elt.Size()
|
||||||
}
|
}
|
||||||
|
|
||||||
case types.TSTRUCT:
|
case types.TSTRUCT:
|
||||||
for _, f := range t.Fields().Slice() {
|
for _, f := range t.Fields().Slice() {
|
||||||
Set(f.Type, off+f.Offset, bv)
|
set(f.Type, off+f.Offset, bv, skip)
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
29
test/fixedbugs/issue54991.go
Normal file
29
test/fixedbugs/issue54991.go
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
// compile
|
||||||
|
|
||||||
|
// Copyright 2022 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.
|
||||||
|
|
||||||
|
package p
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
type I interface {
|
||||||
|
M()
|
||||||
|
}
|
||||||
|
|
||||||
|
type S struct{}
|
||||||
|
|
||||||
|
func (*S) M() {}
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
I
|
||||||
|
x atomic.Int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func F() {
|
||||||
|
t := &T{I: &S{}}
|
||||||
|
t.M()
|
||||||
|
}
|
Loading…
Reference in a new issue