github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/test/abiutilsaux_test.go (about)

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