| // 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 ( |
| "reflect" |
| "sort" |
| "testing" |
| ) |
| |
| func typeWithoutPointers() *Type { |
| return &Type{Etype: TSTRUCT, Extra: &StructType{Haspointers: 1}} // haspointers -> false |
| } |
| |
| func typeWithPointers() *Type { |
| return &Type{Etype: TSTRUCT, Extra: &StructType{Haspointers: 2}} // haspointers -> true |
| } |
| |
| // Test all code paths for cmpstackvarlt. |
| func TestCmpstackvar(t *testing.T) { |
| testdata := []struct { |
| a, b Node |
| lt bool |
| }{ |
| { |
| Node{Class: PAUTO}, |
| Node{Class: PFUNC}, |
| false, |
| }, |
| { |
| Node{Class: PFUNC}, |
| Node{Class: PAUTO}, |
| true, |
| }, |
| { |
| Node{Class: PFUNC, Xoffset: 0}, |
| Node{Class: PFUNC, Xoffset: 10}, |
| true, |
| }, |
| { |
| Node{Class: PFUNC, Xoffset: 20}, |
| Node{Class: PFUNC, Xoffset: 10}, |
| false, |
| }, |
| { |
| Node{Class: PFUNC, Xoffset: 10}, |
| Node{Class: PFUNC, Xoffset: 10}, |
| false, |
| }, |
| { |
| Node{Class: PPARAM, Xoffset: 10}, |
| Node{Class: PPARAMOUT, Xoffset: 20}, |
| true, |
| }, |
| { |
| Node{Class: PPARAMOUT, Xoffset: 10}, |
| Node{Class: PPARAM, Xoffset: 20}, |
| true, |
| }, |
| { |
| Node{Class: PAUTO, Used: true}, |
| Node{Class: PAUTO, Used: false}, |
| true, |
| }, |
| { |
| Node{Class: PAUTO, Used: false}, |
| Node{Class: PAUTO, Used: true}, |
| false, |
| }, |
| { |
| Node{Class: PAUTO, Type: typeWithoutPointers()}, |
| Node{Class: PAUTO, Type: typeWithPointers()}, |
| false, |
| }, |
| { |
| Node{Class: PAUTO, Type: typeWithPointers()}, |
| Node{Class: PAUTO, Type: typeWithoutPointers()}, |
| true, |
| }, |
| { |
| Node{Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: true}}, |
| Node{Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: false}}, |
| true, |
| }, |
| { |
| Node{Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: false}}, |
| Node{Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: true}}, |
| false, |
| }, |
| { |
| Node{Class: PAUTO, Type: &Type{Width: 1}, Name: &Name{}}, |
| Node{Class: PAUTO, Type: &Type{Width: 2}, Name: &Name{}}, |
| false, |
| }, |
| { |
| Node{Class: PAUTO, Type: &Type{Width: 2}, Name: &Name{}}, |
| Node{Class: PAUTO, Type: &Type{Width: 1}, Name: &Name{}}, |
| true, |
| }, |
| { |
| Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}}, |
| Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "xyz"}}, |
| true, |
| }, |
| { |
| Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}}, |
| Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}}, |
| false, |
| }, |
| { |
| Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "xyz"}}, |
| Node{Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}}, |
| 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{ |
| {Class: PFUNC, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PFUNC, Xoffset: 0, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PFUNC, Xoffset: 10, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PFUNC, Xoffset: 20, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PAUTO, Used: true, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PAUTO, Type: typeWithoutPointers(), Name: &Name{}, Sym: &Sym{}}, |
| {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: true}, Sym: &Sym{}}, |
| {Class: PAUTO, Type: &Type{Width: 1}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PAUTO, Type: &Type{Width: 2}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}}, |
| {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "xyz"}}, |
| } |
| want := []*Node{ |
| {Class: PFUNC, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PFUNC, Xoffset: 0, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PFUNC, Xoffset: 10, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PFUNC, Xoffset: 20, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PAUTO, Used: true, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PAUTO, Type: &Type{}, Name: &Name{Needzero: true}, Sym: &Sym{}}, |
| {Class: PAUTO, Type: &Type{Width: 2}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PAUTO, Type: &Type{Width: 1}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{}}, |
| {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "abc"}}, |
| {Class: PAUTO, Type: &Type{}, Name: &Name{}, Sym: &Sym{Name: "xyz"}}, |
| {Class: PAUTO, Type: typeWithoutPointers(), Name: &Name{}, Sym: &Sym{}}, |
| } |
| // haspointers updates Type.Haspointers as a side effect, so |
| // exercise this function on all inputs so that reflect.DeepEqual |
| // doesn't produce false positives. |
| for i := range want { |
| haspointers(want[i].Type) |
| haspointers(inp[i].Type) |
| } |
| |
| 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) |
| } |
| } |
| } |
| } |