Home | History | Annotate | Download | only in gc
      1 // Copyright 2015 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package gc
      6 
      7 import (
      8 	"cmd/compile/internal/types"
      9 	"reflect"
     10 	"sort"
     11 	"testing"
     12 )
     13 
     14 func typeWithoutPointers() *types.Type {
     15 	t := types.New(TSTRUCT)
     16 	f := &types.Field{Type: types.New(TINT)}
     17 	t.SetFields([]*types.Field{f})
     18 	return t
     19 }
     20 
     21 func typeWithPointers() *types.Type {
     22 	t := types.New(TSTRUCT)
     23 	f := &types.Field{Type: types.New(TPTR64)}
     24 	t.SetFields([]*types.Field{f})
     25 	return t
     26 }
     27 
     28 func markUsed(n *Node) *Node {
     29 	n.Name.SetUsed(true)
     30 	return n
     31 }
     32 
     33 func markNeedZero(n *Node) *Node {
     34 	n.Name.SetNeedzero(true)
     35 	return n
     36 }
     37 
     38 func nodeWithClass(n Node, c Class) *Node {
     39 	n.SetClass(c)
     40 	n.Name = new(Name)
     41 	return &n
     42 }
     43 
     44 // Test all code paths for cmpstackvarlt.
     45 func TestCmpstackvar(t *testing.T) {
     46 	testdata := []struct {
     47 		a, b *Node
     48 		lt   bool
     49 	}{
     50 		{
     51 			nodeWithClass(Node{}, PAUTO),
     52 			nodeWithClass(Node{}, PFUNC),
     53 			false,
     54 		},
     55 		{
     56 			nodeWithClass(Node{}, PFUNC),
     57 			nodeWithClass(Node{}, PAUTO),
     58 			true,
     59 		},
     60 		{
     61 			nodeWithClass(Node{Xoffset: 0}, PFUNC),
     62 			nodeWithClass(Node{Xoffset: 10}, PFUNC),
     63 			true,
     64 		},
     65 		{
     66 			nodeWithClass(Node{Xoffset: 20}, PFUNC),
     67 			nodeWithClass(Node{Xoffset: 10}, PFUNC),
     68 			false,
     69 		},
     70 		{
     71 			nodeWithClass(Node{Xoffset: 10}, PFUNC),
     72 			nodeWithClass(Node{Xoffset: 10}, PFUNC),
     73 			false,
     74 		},
     75 		{
     76 			nodeWithClass(Node{Xoffset: 10}, PPARAM),
     77 			nodeWithClass(Node{Xoffset: 20}, PPARAMOUT),
     78 			true,
     79 		},
     80 		{
     81 			nodeWithClass(Node{Xoffset: 10}, PPARAMOUT),
     82 			nodeWithClass(Node{Xoffset: 20}, PPARAM),
     83 			true,
     84 		},
     85 		{
     86 			markUsed(nodeWithClass(Node{}, PAUTO)),
     87 			nodeWithClass(Node{}, PAUTO),
     88 			true,
     89 		},
     90 		{
     91 			nodeWithClass(Node{}, PAUTO),
     92 			markUsed(nodeWithClass(Node{}, PAUTO)),
     93 			false,
     94 		},
     95 		{
     96 			nodeWithClass(Node{Type: typeWithoutPointers()}, PAUTO),
     97 			nodeWithClass(Node{Type: typeWithPointers()}, PAUTO),
     98 			false,
     99 		},
    100 		{
    101 			nodeWithClass(Node{Type: typeWithPointers()}, PAUTO),
    102 			nodeWithClass(Node{Type: typeWithoutPointers()}, PAUTO),
    103 			true,
    104 		},
    105 		{
    106 			markNeedZero(nodeWithClass(Node{Type: &types.Type{}}, PAUTO)),
    107 			nodeWithClass(Node{Type: &types.Type{}, Name: &Name{}}, PAUTO),
    108 			true,
    109 		},
    110 		{
    111 			nodeWithClass(Node{Type: &types.Type{}, Name: &Name{}}, PAUTO),
    112 			markNeedZero(nodeWithClass(Node{Type: &types.Type{}}, PAUTO)),
    113 			false,
    114 		},
    115 		{
    116 			nodeWithClass(Node{Type: &types.Type{Width: 1}, Name: &Name{}}, PAUTO),
    117 			nodeWithClass(Node{Type: &types.Type{Width: 2}, Name: &Name{}}, PAUTO),
    118 			false,
    119 		},
    120 		{
    121 			nodeWithClass(Node{Type: &types.Type{Width: 2}, Name: &Name{}}, PAUTO),
    122 			nodeWithClass(Node{Type: &types.Type{Width: 1}, Name: &Name{}}, PAUTO),
    123 			true,
    124 		},
    125 		{
    126 			nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "abc"}}, PAUTO),
    127 			nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "xyz"}}, PAUTO),
    128 			true,
    129 		},
    130 		{
    131 			nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "abc"}}, PAUTO),
    132 			nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "abc"}}, PAUTO),
    133 			false,
    134 		},
    135 		{
    136 			nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "xyz"}}, PAUTO),
    137 			nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "abc"}}, PAUTO),
    138 			false,
    139 		},
    140 	}
    141 	for _, d := range testdata {
    142 		got := cmpstackvarlt(d.a, d.b)
    143 		if got != d.lt {
    144 			t.Errorf("want %#v < %#v", d.a, d.b)
    145 		}
    146 		// If we expect a < b to be true, check that b < a is false.
    147 		if d.lt && cmpstackvarlt(d.b, d.a) {
    148 			t.Errorf("unexpected %#v < %#v", d.b, d.a)
    149 		}
    150 	}
    151 }
    152 
    153 func TestStackvarSort(t *testing.T) {
    154 	inp := []*Node{
    155 		nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
    156 		nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO),
    157 		nodeWithClass(Node{Xoffset: 0, Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
    158 		nodeWithClass(Node{Xoffset: 10, Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
    159 		nodeWithClass(Node{Xoffset: 20, Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
    160 		markUsed(nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO)),
    161 		nodeWithClass(Node{Type: typeWithoutPointers(), Sym: &types.Sym{}}, PAUTO),
    162 		nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO),
    163 		markNeedZero(nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO)),
    164 		nodeWithClass(Node{Type: &types.Type{Width: 1}, Sym: &types.Sym{}}, PAUTO),
    165 		nodeWithClass(Node{Type: &types.Type{Width: 2}, Sym: &types.Sym{}}, PAUTO),
    166 		nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "abc"}}, PAUTO),
    167 		nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "xyz"}}, PAUTO),
    168 	}
    169 	want := []*Node{
    170 		nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
    171 		nodeWithClass(Node{Xoffset: 0, Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
    172 		nodeWithClass(Node{Xoffset: 10, Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
    173 		nodeWithClass(Node{Xoffset: 20, Type: &types.Type{}, Sym: &types.Sym{}}, PFUNC),
    174 		markUsed(nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO)),
    175 		markNeedZero(nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO)),
    176 		nodeWithClass(Node{Type: &types.Type{Width: 2}, Sym: &types.Sym{}}, PAUTO),
    177 		nodeWithClass(Node{Type: &types.Type{Width: 1}, Sym: &types.Sym{}}, PAUTO),
    178 		nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO),
    179 		nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{}}, PAUTO),
    180 		nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "abc"}}, PAUTO),
    181 		nodeWithClass(Node{Type: &types.Type{}, Sym: &types.Sym{Name: "xyz"}}, PAUTO),
    182 		nodeWithClass(Node{Type: typeWithoutPointers(), Sym: &types.Sym{}}, PAUTO),
    183 	}
    184 	// haspointers updates Type.Haspointers as a side effect, so
    185 	// exercise this function on all inputs so that reflect.DeepEqual
    186 	// doesn't produce false positives.
    187 	for i := range want {
    188 		types.Haspointers(want[i].Type)
    189 		types.Haspointers(inp[i].Type)
    190 	}
    191 
    192 	sort.Sort(byStackVar(inp))
    193 	if !reflect.DeepEqual(want, inp) {
    194 		t.Error("sort failed")
    195 		for i := range inp {
    196 			g := inp[i]
    197 			w := want[i]
    198 			eq := reflect.DeepEqual(w, g)
    199 			if !eq {
    200 				t.Log(i, w, g)
    201 			}
    202 		}
    203 	}
    204 }
    205