// 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 ssagen import ( "reflect" "sort" "testing" "cmd/compile/internal/ir" "cmd/compile/internal/typecheck" "cmd/compile/internal/types" "cmd/internal/src" ) func typeWithoutPointers() *types.Type { return types.NewStruct(types.NoPkg, []*types.Field{ types.NewField(src.NoXPos, nil, types.New(types.TINT)), }) } func typeWithPointers() *types.Type { return types.NewStruct(types.NoPkg, []*types.Field{ types.NewField(src.NoXPos, nil, types.NewPtr(types.New(types.TINT))), }) } func markUsed(n *ir.Name) *ir.Name { n.SetUsed(true) return n } func markNeedZero(n *ir.Name) *ir.Name { n.SetNeedzero(true) return n } // Test all code paths for cmpstackvarlt. func TestCmpstackvar(t *testing.T) { nod := func(xoffset int64, t *types.Type, s *types.Sym, cl ir.Class) *ir.Name { if s == nil { s = &types.Sym{Name: "."} } n := typecheck.NewName(s) n.SetType(t) n.SetFrameOffset(xoffset) n.Class = cl return n } testdata := []struct { a, b *ir.Name lt bool }{ { nod(0, nil, nil, ir.PAUTO), nod(0, nil, nil, ir.PFUNC), false, }, { nod(0, nil, nil, ir.PFUNC), nod(0, nil, nil, ir.PAUTO), true, }, { nod(0, nil, nil, ir.PFUNC), nod(10, nil, nil, ir.PFUNC), true, }, { nod(20, nil, nil, ir.PFUNC), nod(10, nil, nil, ir.PFUNC), false, }, { nod(10, nil, nil, ir.PFUNC), nod(10, nil, nil, ir.PFUNC), false, }, { nod(10, nil, nil, ir.PPARAM), nod(20, nil, nil, ir.PPARAMOUT), true, }, { nod(10, nil, nil, ir.PPARAMOUT), nod(20, nil, nil, ir.PPARAM), true, }, { markUsed(nod(0, nil, nil, ir.PAUTO)), nod(0, nil, nil, ir.PAUTO), true, }, { nod(0, nil, nil, ir.PAUTO), markUsed(nod(0, nil, nil, ir.PAUTO)), false, }, { nod(0, typeWithoutPointers(), nil, ir.PAUTO), nod(0, typeWithPointers(), nil, ir.PAUTO), false, }, { nod(0, typeWithPointers(), nil, ir.PAUTO), nod(0, typeWithoutPointers(), nil, ir.PAUTO), true, }, { markNeedZero(nod(0, &types.Type{}, nil, ir.PAUTO)), nod(0, &types.Type{}, nil, ir.PAUTO), true, }, { nod(0, &types.Type{}, nil, ir.PAUTO), markNeedZero(nod(0, &types.Type{}, nil, ir.PAUTO)), false, }, { nod(0, &types.Type{Width: 1}, nil, ir.PAUTO), nod(0, &types.Type{Width: 2}, nil, ir.PAUTO), false, }, { nod(0, &types.Type{Width: 2}, nil, ir.PAUTO), nod(0, &types.Type{Width: 1}, nil, ir.PAUTO), true, }, { nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, ir.PAUTO), true, }, { nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), false, }, { nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, ir.PAUTO), nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.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) { nod := func(xoffset int64, t *types.Type, s *types.Sym, cl ir.Class) *ir.Name { n := typecheck.NewName(s) n.SetType(t) n.SetFrameOffset(xoffset) n.Class = cl return n } inp := []*ir.Name{ nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO), nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), nod(10, &types.Type{}, &types.Sym{}, ir.PFUNC), nod(20, &types.Type{}, &types.Sym{}, ir.PFUNC), markUsed(nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO)), nod(0, typeWithoutPointers(), &types.Sym{}, ir.PAUTO), nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO), markNeedZero(nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO)), nod(0, &types.Type{Width: 1}, &types.Sym{}, ir.PAUTO), nod(0, &types.Type{Width: 2}, &types.Sym{}, ir.PAUTO), nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, ir.PAUTO), } want := []*ir.Name{ nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), nod(0, &types.Type{}, &types.Sym{}, ir.PFUNC), nod(10, &types.Type{}, &types.Sym{}, ir.PFUNC), nod(20, &types.Type{}, &types.Sym{}, ir.PFUNC), markUsed(nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO)), markNeedZero(nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO)), nod(0, &types.Type{Width: 2}, &types.Sym{}, ir.PAUTO), nod(0, &types.Type{Width: 1}, &types.Sym{}, ir.PAUTO), nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO), nod(0, &types.Type{}, &types.Sym{}, ir.PAUTO), nod(0, &types.Type{}, &types.Sym{Name: "abc"}, ir.PAUTO), nod(0, &types.Type{}, &types.Sym{Name: "xyz"}, ir.PAUTO), nod(0, typeWithoutPointers(), &types.Sym{}, ir.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) } } } }