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 }