From: Cuong Manh Le Date: Fri, 16 Sep 2022 03:41:15 +0000 (+0700) Subject: [release-branch.go1.19] cmd/compile/internal/typebits: relax alignment check X-Git-Tag: go1.19.2~4 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=2614985ef7d252004c8bd2edddb7314446964874;p=gostls13.git [release-branch.go1.19] 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 #55152 Change-Id: I34986e17a920254392a39439ad3dcb323da2ea8d Reviewed-on: https://go-review.googlesource.com/c/go/+/431098 Reviewed-by: Keith Randall TryBot-Result: Gopher Robot Reviewed-by: Cherry Mui Run-TryBot: Cuong Manh Le Auto-Submit: Keith Randall Reviewed-by: Keith Randall Reviewed-on: https://go-review.googlesource.com/c/go/+/431895 --- diff --git a/src/cmd/compile/internal/liveness/plive.go b/src/cmd/compile/internal/liveness/plive.go index 93f49fad45..4e5a52ee54 100644 --- a/src/cmd/compile/internal/liveness/plive.go +++ b/src/cmd/compile/internal/liveness/plive.go @@ -434,7 +434,7 @@ func (lv *liveness) pointerMap(liveout bitvec.BitVec, vars []*ir.Name, args, loc if node.FrameOffset() < 0 { 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 } fallthrough // PPARAMOUT in registers acts memory-allocates like an AUTO @@ -1507,7 +1507,7 @@ func WriteFuncMap(fn *ir.Func, abiInfo *abi.ABIParamResultInfo) { bv := bitvec.New(int32(nptr) * 2) for _, p := range abiInfo.InParams() { - typebits.Set(p.Type, p.FrameOffset(abiInfo), bv) + typebits.SetNoCheck(p.Type, p.FrameOffset(abiInfo), bv) } nbitmap := 1 @@ -1522,7 +1522,7 @@ func WriteFuncMap(fn *ir.Func, abiInfo *abi.ABIParamResultInfo) { if fn.Type().NumResults() > 0 { for _, p := range abiInfo.OutParams() { 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) diff --git a/src/cmd/compile/internal/typebits/typebits.go b/src/cmd/compile/internal/typebits/typebits.go index fddad6e7e8..cd52830a49 100644 --- a/src/cmd/compile/internal/typebits/typebits.go +++ b/src/cmd/compile/internal/typebits/typebits.go @@ -14,7 +14,16 @@ import ( // the first run and then simply copied into bv at the correct offset // on future calls with the same type t. 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) } if !t.HasPointers() { @@ -72,13 +81,13 @@ func Set(t *types.Type, off int64, bv bitvec.BitVec) { break } for i := int64(0); i < t.NumElem(); i++ { - Set(elt, off, bv) + set(elt, off, bv, skip) off += elt.Size() } case types.TSTRUCT: for _, f := range t.Fields().Slice() { - Set(f.Type, off+f.Offset, bv) + set(f.Type, off+f.Offset, bv, skip) } default: diff --git a/test/fixedbugs/issue54991.go b/test/fixedbugs/issue54991.go new file mode 100644 index 0000000000..9ab0f5d06c --- /dev/null +++ b/test/fixedbugs/issue54991.go @@ -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() +}