| // 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. | |
| package ssa | |
| import ( | |
| "cmd/compile/internal/types" | |
| "testing" | |
| ) | |
| func TestWriteBarrierStoreOrder(t *testing.T) { | |
| // Make sure writebarrier phase works even StoreWB ops are not in dependency order | |
| c := testConfig(t) | |
| ptrType := c.config.Types.BytePtr | |
| fun := c.Fun("entry", | |
| Bloc("entry", | |
| Valu("start", OpInitMem, types.TypeMem, 0, nil), | |
| Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil), | |
| Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil), | |
| Valu("v", OpConstNil, ptrType, 0, nil), | |
| Valu("addr1", OpAddr, ptrType, 0, nil, "sb"), | |
| Valu("wb2", OpStore, types.TypeMem, 0, ptrType, "addr1", "v", "wb1"), | |
| Valu("wb1", OpStore, types.TypeMem, 0, ptrType, "addr1", "v", "start"), // wb1 and wb2 are out of order | |
| Goto("exit")), | |
| Bloc("exit", | |
| Exit("wb2"))) | |
| CheckFunc(fun.f) | |
| writebarrier(fun.f) | |
| CheckFunc(fun.f) | |
| } | |
| func TestWriteBarrierPhi(t *testing.T) { | |
| // Make sure writebarrier phase works for single-block loop, where | |
| // a Phi op takes the store in the same block as argument. | |
| // See issue #19067. | |
| c := testConfig(t) | |
| ptrType := c.config.Types.BytePtr | |
| fun := c.Fun("entry", | |
| Bloc("entry", | |
| Valu("start", OpInitMem, types.TypeMem, 0, nil), | |
| Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil), | |
| Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil), | |
| Goto("loop")), | |
| Bloc("loop", | |
| Valu("phi", OpPhi, types.TypeMem, 0, nil, "start", "wb"), | |
| Valu("v", OpConstNil, ptrType, 0, nil), | |
| Valu("addr", OpAddr, ptrType, 0, nil, "sb"), | |
| Valu("wb", OpStore, types.TypeMem, 0, ptrType, "addr", "v", "phi"), // has write barrier | |
| Goto("loop"))) | |
| CheckFunc(fun.f) | |
| writebarrier(fun.f) | |
| CheckFunc(fun.f) | |
| } |