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 "reflect" 9 "sort" 10 "testing" 11 ) 12 13 func typeWithoutPointers() *Type { 14 return &Type{Etype: TSTRUCT, Extra: &StructType{Haspointers: 1}} // haspointers -> false 15 } 16 17 func typeWithPointers() *Type { 18 return &Type{Etype: TSTRUCT, Extra: &StructType{Haspointers: 2}} // haspointers -> true 19 } 20 21 // Test all code paths for cmpstackvarlt. 22 func TestCmpstackvar(t *testing.T) { 23 testdata := []struct { 24 a, b Node 25 lt bool 26 }{ 27 { 28 Node{Class: PAUTO}, 29 Node{Class: PFUNC}, 30 false, 31 }, 32 { 33 Node{Class: PFUNC}, 34 Node{Class: PAUTO}, 35 true, 36 }, 37 { 38 Node{Class: PFUNC, Xoffset: 0}, 39 Node{Class: PFUNC, Xoffset: 10}, 40 true, 41 }, 42 { 43 Node{Class: PFUNC, Xoffset: 20}, 44 Node{Class: PFUNC, Xoffset: 10}, 45 false, 46 }, 47 { 48 Node{Class: PFUNC, Xoffset: 10}, 49 Node{Class: PFUNC, Xoffset: 10}, 50 false, 51 }, 52 { 53 Node{Class: PPARAM, Xoffset: 10}, 54 Node{Class: PPARAMOUT, Xoffset: 20}, 55 true, 56 }, 57 { 58 Node{Class: PPARAMOUT, Xoffset: 10}, 59 Node{Class: PPARAM, Xoffset: 20}, 60 true, 61 }, 62 { 63 Node{Class: PAUTO, Used: true}, 64 Node{Class: PAUTO, Used: false}, 65 true, 66 }, 67 { 68 Node{Class: PAUTO, Used: false}, 69 Node{Class: PAUTO, Used: true}, 70 false, 71 }, 72 { 73 Node{Class: PAUTO, Type: typeWithoutPointers()}, 74 Node{Class: PAUTO, Type: typeWithPointers()}, 75 false, 76 }, 77 { 78 Node{Class: PAUTO, Type: typeWithPointers()}, 79 Node{Class: PAUTO, Type: typeWithoutPointers()}, 80 true, 81 }, 82 { 83 Node{Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: true}}, 84 Node{Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: false}}, 85 true, 86 }, 87 { 88 Node{Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: false}}, 89 Node{Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: true}}, 90 false, 91 }, 92 { 93 Node{Class: PAUTO, Type: &Type{Width: 1}, Name: &Name{}}, 94 Node{Class: PAUTO, Type: &Type{Width: 2}, Name: &Name{}}, 95 false, 96 }, 97 { 98 Node{Class: PAUTO, Type: &Type{Width: 2}, Name: &Name{}}, 99 Node{Class: PAUTO, Type: &Type{Width: 1}, Name: &Name{}}, 100 true, 101 }, 102 { 103 Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}}, 104 Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "xyz"}}, 105 true, 106 }, 107 { 108 Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}}, 109 Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}}, 110 false, 111 }, 112 { 113 Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "xyz"}}, 114 Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}}, 115 false, 116 }, 117 } 118 for _, d := range testdata { 119 got := cmpstackvarlt(&d.a, &d.b) 120 if got != d.lt { 121 t.Errorf("want %#v < %#v", d.a, d.b) 122 } 123 // If we expect a < b to be true, check that b < a is false. 124 if d.lt && cmpstackvarlt(&d.b, &d.a) { 125 t.Errorf("unexpected %#v < %#v", d.b, d.a) 126 } 127 } 128 } 129 130 func TestStackvarSort(t *testing.T) { 131 inp := []*Node{ 132 {Class: PFUNC, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, 133 {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, 134 {Class: PFUNC, Xoffset: 0, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, 135 {Class: PFUNC, Xoffset: 10, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, 136 {Class: PFUNC, Xoffset: 20, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, 137 {Class: PAUTO, Used: true, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, 138 {Class: PAUTO, Type: typeWithoutPointers(), Name: &Name{}, Sym: &Sym{}}, 139 {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, 140 {Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: true}, Sym: &Sym{}}, 141 {Class: PAUTO, Type: &Type{Width: 1}, Name: &Name{}, Sym: &Sym{}}, 142 {Class: PAUTO, Type: &Type{Width: 2}, Name: &Name{}, Sym: &Sym{}}, 143 {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}}, 144 {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "xyz"}}, 145 } 146 want := []*Node{ 147 {Class: PFUNC, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, 148 {Class: PFUNC, Xoffset: 0, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, 149 {Class: PFUNC, Xoffset: 10, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, 150 {Class: PFUNC, Xoffset: 20, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, 151 {Class: PAUTO, Used: true, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, 152 {Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: true}, Sym: &Sym{}}, 153 {Class: PAUTO, Type: &Type{Width: 2}, Name: &Name{}, Sym: &Sym{}}, 154 {Class: PAUTO, Type: &Type{Width: 1}, Name: &Name{}, Sym: &Sym{}}, 155 {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, 156 {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, 157 {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}}, 158 {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "xyz"}}, 159 {Class: PAUTO, Type: typeWithoutPointers(), Name: &Name{}, Sym: &Sym{}}, 160 } 161 // haspointers updates Type.Haspointers as a side effect, so 162 // exercise this function on all inputs so that reflect.DeepEqual 163 // doesn't produce false positives. 164 for i := range want { 165 haspointers(want[i].Type) 166 haspointers(inp[i].Type) 167 } 168 169 sort.Sort(byStackVar(inp)) 170 if !reflect.DeepEqual(want, inp) { 171 t.Error("sort failed") 172 for i := range inp { 173 g := inp[i] 174 w := want[i] 175 eq := reflect.DeepEqual(w, g) 176 if !eq { 177 t.Log(i, w, g) 178 } 179 } 180 } 181 } 182