diff --git a/src/cmd/compile/internal/arm/ggen.go b/src/cmd/compile/internal/arm/ggen.go index d241357d62c..4a45e589ebd 100644 --- a/src/cmd/compile/internal/arm/ggen.go +++ b/src/cmd/compile/internal/arm/ggen.go @@ -341,6 +341,11 @@ func clearfat(nl *gc.Node) { c := w % 4 // bytes q := w / 4 // quads + if nl.Type.Align < 4 { + q = 0 + c = w + } + var r0 gc.Node r0.Op = gc.OREGISTER @@ -395,6 +400,27 @@ func clearfat(nl *gc.Node) { } } + if c > 4 { + // Loop to zero unaligned memory. + var end gc.Node + gc.Regalloc(&end, gc.Types[gc.Tptr], nil) + p := gins(arm.AMOVW, &dst, &end) + p.From.Type = obj.TYPE_ADDR + p.From.Offset = int64(c) + + p = gins(arm.AMOVB, &nz, &dst) + p.To.Type = obj.TYPE_MEM + p.To.Offset = 1 + p.Scond |= arm.C_PBIT + pl := p + + p = gins(arm.ACMP, &dst, nil) + raddr(&end, p) + gc.Patch(gc.Gbranch(arm.ABNE, nil, 0), pl) + + gc.Regfree(&end) + c = 0 + } var p *obj.Prog for c > 0 { p = gins(arm.AMOVB, &nz, &dst) diff --git a/test/fixedbugs/issue15902.go b/test/fixedbugs/issue15902.go new file mode 100644 index 00000000000..9511a220edb --- /dev/null +++ b/test/fixedbugs/issue15902.go @@ -0,0 +1,27 @@ +// run + +// Copyright 2016 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. + +// This test makes sure we don't use 4-byte unaligned writes +// to zero memory on architectures that don't support them. + +package main + +type T struct { + a byte + b [10]byte +} + +//go:noinline +func f(t *T) { + // t will be aligned, so &t.b won't be. + t.b = [10]byte{} +} + +var t T + +func main() { + f(&t) +}