]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.19] cmd/compile/internal/typebits: relax alignment check
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Fri, 16 Sep 2022 03:41:15 +0000 (10:41 +0700)
committerCherry Mui <cherryyz@google.com>
Wed, 21 Sep 2022 22:25:31 +0000 (22:25 +0000)
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 <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>
Reviewed-on: https://go-review.googlesource.com/c/go/+/431895

src/cmd/compile/internal/liveness/plive.go
src/cmd/compile/internal/typebits/typebits.go
test/fixedbugs/issue54991.go [new file with mode: 0644]

index 93f49fad454cb0c8107c964a7f4823e3a80ddfff..4e5a52ee547607d2679f63cf3b62c5233630153f 100644 (file)
@@ -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)
index fddad6e7e84b8176fd3d2865433d53d0b95236b2..cd52830a49d03d7a1dca562c4f4143c3062fe8fa 100644 (file)
@@ -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 (file)
index 0000000..9ab0f5d
--- /dev/null
@@ -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()
+}