Source file src/cmd/compile/internal/test/abiutilsaux_test.go

     1  // Copyright 2020 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 test
     6  
     7  // This file contains utility routines and harness infrastructure used
     8  // by the ABI tests in "abiutils_test.go".
     9  
    10  import (
    11  	"cmd/compile/internal/abi"
    12  	"cmd/compile/internal/ir"
    13  	"cmd/compile/internal/typecheck"
    14  	"cmd/compile/internal/types"
    15  	"cmd/internal/src"
    16  	"fmt"
    17  	"strings"
    18  	"testing"
    19  	"text/scanner"
    20  )
    21  
    22  func mkParamResultField(t *types.Type, s *types.Sym, which ir.Class) *types.Field {
    23  	field := types.NewField(src.NoXPos, s, t)
    24  	n := ir.NewNameAt(src.NoXPos, s, t)
    25  	n.Class = which
    26  	field.Nname = n
    27  	return field
    28  }
    29  
    30  // mkstruct is a helper routine to create a struct type with fields
    31  // of the types specified in 'fieldtypes'.
    32  func mkstruct(fieldtypes ...*types.Type) *types.Type {
    33  	fields := make([]*types.Field, len(fieldtypes))
    34  	for k, t := range fieldtypes {
    35  		if t == nil {
    36  			panic("bad -- field has no type")
    37  		}
    38  		f := types.NewField(src.NoXPos, nil, t)
    39  		fields[k] = f
    40  	}
    41  	s := types.NewStruct(fields)
    42  	return s
    43  }
    44  
    45  func mkFuncType(rcvr *types.Type, ins []*types.Type, outs []*types.Type) *types.Type {
    46  	q := typecheck.Lookup("?")
    47  	inf := []*types.Field{}
    48  	for _, it := range ins {
    49  		inf = append(inf, mkParamResultField(it, q, ir.PPARAM))
    50  	}
    51  	outf := []*types.Field{}
    52  	for _, ot := range outs {
    53  		outf = append(outf, mkParamResultField(ot, q, ir.PPARAMOUT))
    54  	}
    55  	var rf *types.Field
    56  	if rcvr != nil {
    57  		rf = mkParamResultField(rcvr, q, ir.PPARAM)
    58  	}
    59  	return types.NewSignature(rf, inf, outf)
    60  }
    61  
    62  type expectedDump struct {
    63  	dump string
    64  	file string
    65  	line int
    66  }
    67  
    68  func tokenize(src string) []string {
    69  	var s scanner.Scanner
    70  	s.Init(strings.NewReader(src))
    71  	res := []string{}
    72  	for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
    73  		res = append(res, s.TokenText())
    74  	}
    75  	return res
    76  }
    77  
    78  func verifyParamResultOffset(t *testing.T, f *types.Field, r abi.ABIParamAssignment, which string, idx int) int {
    79  	n := f.Nname.(*ir.Name)
    80  	if n.FrameOffset() != int64(r.Offset()) {
    81  		t.Errorf("%s %d: got offset %d wanted %d t=%v",
    82  			which, idx, r.Offset(), n.Offset_, f.Type)
    83  		return 1
    84  	}
    85  	return 0
    86  }
    87  
    88  func makeExpectedDump(e string) expectedDump {
    89  	return expectedDump{dump: e}
    90  }
    91  
    92  func difftokens(atoks []string, etoks []string) string {
    93  	if len(atoks) != len(etoks) {
    94  		return fmt.Sprintf("expected %d tokens got %d",
    95  			len(etoks), len(atoks))
    96  	}
    97  	for i := 0; i < len(etoks); i++ {
    98  		if etoks[i] == atoks[i] {
    99  			continue
   100  		}
   101  
   102  		return fmt.Sprintf("diff at token %d: expected %q got %q",
   103  			i, etoks[i], atoks[i])
   104  	}
   105  	return ""
   106  }
   107  
   108  func nrtest(t *testing.T, ft *types.Type, expected int) {
   109  	types.CalcSize(ft)
   110  	got := configAMD64.NumParamRegs(ft)
   111  	if got != expected {
   112  		t.Errorf("]\nexpected num regs = %d, got %d, type %v", expected, got, ft)
   113  	}
   114  }
   115  
   116  func abitest(t *testing.T, ft *types.Type, exp expectedDump) {
   117  
   118  	types.CalcSize(ft)
   119  
   120  	// Analyze with full set of registers.
   121  	regRes := configAMD64.ABIAnalyze(ft, false)
   122  	regResString := strings.TrimSpace(regRes.String())
   123  
   124  	// Check results.
   125  	reason := difftokens(tokenize(regResString), tokenize(exp.dump))
   126  	if reason != "" {
   127  		t.Errorf("\nexpected:\n%s\ngot:\n%s\nreason: %s",
   128  			strings.TrimSpace(exp.dump), regResString, reason)
   129  	}
   130  
   131  }
   132  

View as plain text