mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
Right now we just prevent such types from being on the heap. This CL makes it so they cannot appear on the stack either. The distinction between heap and stack is pretty vague at the language level (e.g. it is affected by -N), and we don't need the flexibility anyway. Once go:notinheap types cannot be in either place, we don't need to consider pointers to such types to be pointers, at least according to the garbage collector and stack copying. (This is the big win of this CL, in my opinion.) The distinction between HasPointers and HasHeapPointer no longer exists. There is only HasPointers. This CL is cleanup before possible use of go:notinheap to fix #40954. Update #13386 Change-Id: Ibd895aadf001c0385078a6d4809c3f374991231a Reviewed-on: https://go-review.googlesource.com/c/go/+/249917 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
196 lines
5.8 KiB
Go
196 lines
5.8 KiB
Go
// Copyright 2015 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 gc
|
|
|
|
import (
|
|
"cmd/compile/internal/types"
|
|
"reflect"
|
|
"sort"
|
|
"testing"
|
|
)
|
|
|
|
func typeWithoutPointers() *types.Type {
|
|
t := types.New(TSTRUCT)
|
|
f := &types.Field{Type: types.New(TINT)}
|
|
t.SetFields([]*types.Field{f})
|
|
return t
|
|
}
|
|
|
|
func typeWithPointers() *types.Type {
|
|
t := types.New(TSTRUCT)
|
|
f := &types.Field{Type: types.NewPtr(types.New(TINT))}
|
|
t.SetFields([]*types.Field{f})
|
|
return t
|
|
}
|
|
|
|
func markUsed(n *Node) *Node {
|
|
n.Name.SetUsed(true)
|
|
return n
|
|
}
|
|
|
|
func markNeedZero(n *Node) *Node {
|
|
n.Name.SetNeedzero(true)
|
|
return n
|
|
}
|
|
|
|
func nodeWithClass(n Node, c Class) *Node {
|
|
n.SetClass(c)
|
|
n.Name = new(Name)
|
|
return &n
|
|
}
|
|
|
|
// Test all code paths for cmpstackvarlt.
|
|
func TestCmpstackvar(t *testing.T) {
|
|
testdata := []struct {
|
|
a, b *Node
|
|
lt bool
|
|
}{
|
|
{
|
|
nodeWithClass(Node{}, PAUTO),
|
|
nodeWithClass(Node{}, PFUNC),
|
|
false,
|
|
},
|
|
{
|
|
nodeWithClass(Node{}, PFUNC),
|
|
nodeWithClass(Node{}, PAUTO),
|
|
true,
|
|
},
|
|
{
|
|
nodeWithClass(Node{Xoffset: 0}, PFUNC),
|
|
nodeWithClass(Node{Xoffset: 10}, PFUNC),
|
|
true,
|
|
},
|
|
{
|
|
nodeWithClass(Node{Xoffset: 20}, PFUNC),
|
|
nodeWithClass(Node{Xoffset: 10}, PFUNC),
|
|
false,
|
|
},
|
|
{
|
|
nodeWithClass(Node{Xoffset: 10}, PFUNC),
|
|
nodeWithClass(Node{Xoffset: 10}, PFUNC),
|
|
false,
|
|
},
|
|
{
|
|
nodeWithClass(Node{Xoffset: 10}, PPARAM),
|
|
nodeWithClass(Node{Xoffset: 20}, PPARAMOUT),
|
|
true,
|
|
},
|
|
{
|
|
nodeWithClass(Node{Xoffset: 10}, PPARAMOUT),
|
|
nodeWithClass(Node{Xoffset: 20}, PPARAM),
|
|
true,
|
|
},
|
|
{
|
|
markUsed(nodeWithClass(Node{}, PAUTO)),
|
|
nodeWithClass(Node{}, PAUTO),
|
|
true,
|
|
},
|
|
{
|
|
nodeWithClass(Node{}, PAUTO),
|
|
markUsed(nodeWithClass(Node{}, PAUTO)),
|
|
false,
|
|
},
|
|
{
|
|
nodeWithClass(Node{Type: typeWithoutPointers()}, PAUTO),
|
|
nodeWithClass(Node{Type: typeWithPointers()}, PAUTO),
|
|
false,
|
|
},
|
|
{
|
|
nodeWithClass(Node{Type: typeWithPointers()}, PAUTO),
|
|
nodeWithClass(Node{Type: typeWithoutPointers()}, PAUTO),
|
|
true,
|
|
},
|
|
{
|
|
markNeedZero(nodeWithClass(Node{Type: &types.Type{}}, PAUTO)),
|
|
nodeWithClass(Node{Type: &types.Type{}, Name: &Name{}}, PAUTO),
|
|
true,
|
|
},
|
|
{
|
|
nodeWithClass(Node{Type: &types.Type{}, Name: &Name{}}, PAUTO),
|
|
markNeedZero(nodeWithClass(Node{Type: &types.Type{}}, PAUTO)),
|
|
false,
|
|
},
|
|
{
|
|
nodeWithClass(Node{Type: &types.Type{Width: 1}, Name: &Name{}}, PAUTO),
|
|
nodeWithClass(Node{Type: &types.Type{Width: 2}, Name: &Name{}}, PAUTO),
|
|
false,
|
|
},
|
|
{
|
|
nodeWithClass(Node{Type: &types.Type{Width: 2}, Name: &Name{}}, PAUTO),
|
|
nodeWithClass(Node{Type: &types.Type{Width: 1}, Name: &Name{}}, PAUTO),
|
|
true,
|
|
},
|
|
{
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "abc"}}, PAUTO),
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "xyz"}}, PAUTO),
|
|
true,
|
|
},
|
|
{
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "abc"}}, PAUTO),
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "abc"}}, PAUTO),
|
|
false,
|
|
},
|
|
{
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "xyz"}}, PAUTO),
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "abc"}}, PAUTO),
|
|
false,
|
|
},
|
|
}
|
|
for _, d := range testdata {
|
|
got := cmpstackvarlt(d.a, d.b)
|
|
if got != d.lt {
|
|
t.Errorf("want %#v < %#v", d.a, d.b)
|
|
}
|
|
// If we expect a < b to be true, check that b < a is false.
|
|
if d.lt && cmpstackvarlt(d.b, d.a) {
|
|
t.Errorf("unexpected %#v < %#v", d.b, d.a)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStackvarSort(t *testing.T) {
|
|
inp := []*Node{
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO),
|
|
nodeWithClass(Node{Xoffset: 0, Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
|
|
nodeWithClass(Node{Xoffset: 10, Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
|
|
nodeWithClass(Node{Xoffset: 20, Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
|
|
markUsed(nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO)),
|
|
nodeWithClass(Node{Type: typeWithoutPointers(), Sym: &types.Sym{}}, PAUTO),
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO),
|
|
markNeedZero(nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO)),
|
|
nodeWithClass(Node{Type: &types.Type{Width: 1}, Sym: &types.Sym{}}, PAUTO),
|
|
nodeWithClass(Node{Type: &types.Type{Width: 2}, Sym: &types.Sym{}}, PAUTO),
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "abc"}}, PAUTO),
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "xyz"}}, PAUTO),
|
|
}
|
|
want := []*Node{
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
|
|
nodeWithClass(Node{Xoffset: 0, Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
|
|
nodeWithClass(Node{Xoffset: 10, Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
|
|
nodeWithClass(Node{Xoffset: 20, Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
|
|
markUsed(nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO)),
|
|
markNeedZero(nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO)),
|
|
nodeWithClass(Node{Type: &types.Type{Width: 2}, Sym: &types.Sym{}}, PAUTO),
|
|
nodeWithClass(Node{Type: &types.Type{Width: 1}, Sym: &types.Sym{}}, PAUTO),
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO),
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO),
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "abc"}}, PAUTO),
|
|
nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "xyz"}}, PAUTO),
|
|
nodeWithClass(Node{Type: typeWithoutPointers(), Sym: &types.Sym{}}, PAUTO),
|
|
}
|
|
sort.Sort(byStackVar(inp))
|
|
if !reflect.DeepEqual(want, inp) {
|
|
t.Error("sort failed")
|
|
for i := range inp {
|
|
g := inp[i]
|
|
w := want[i]
|
|
eq := reflect.DeepEqual(w, g)
|
|
if !eq {
|
|
t.Log(i, w, g)
|
|
}
|
|
}
|
|
}
|
|
}
|