Source file src/simd/archsimd/_gen/specgen/api.go

     1  // Copyright 2026 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 specgen
     6  
     7  import (
     8  	"fmt"
     9  	"go/token"
    10  	"go/types"
    11  	"simd/archsimd/_gen/specgen/specexpr"
    12  	"strings"
    13  )
    14  
    15  // Func represents a function or method in the SIMD API.
    16  type Func struct {
    17  	Name string
    18  
    19  	// Doc is the function documentation, without any leading comment markers
    20  	Doc string
    21  
    22  	// Commutative indicates that this operation produces the same result
    23  	// regardless of the order of its arguments in Recv and In.
    24  	Commutative bool
    25  
    26  	// The general category of this function or method (useful for overview
    27  	// documentation).
    28  	Category string
    29  
    30  	// Recv, if non-zero, is the shape of the receiver. The name of the receiver
    31  	// is always "x".
    32  	Recv Arg
    33  
    34  	In  []Arg
    35  	Out []Arg
    36  
    37  	// Pos is the source position of this definition.
    38  	Pos token.Position
    39  
    40  	// specFunc and instance describe the underlying spec function and its
    41  	// instantiation that led to this API function.
    42  	specFunc      *specFunc
    43  	typeParamVars map[*types.TypeParam]specexpr.Variable
    44  	instance      *specexpr.Bindings
    45  }
    46  
    47  type Arg struct {
    48  	Name string
    49  	Type specexpr.Type
    50  }
    51  
    52  func (f *Func) Signature() string {
    53  	var buf strings.Builder
    54  	buf.WriteString("func ")
    55  	argList := func(args []Arg, canShort bool) {
    56  		if canShort {
    57  			if len(args) == 0 {
    58  				return
    59  			} else if len(args) == 1 && args[0].Name == "" {
    60  				buf.WriteString(args[0].Type.String())
    61  				return
    62  			}
    63  		}
    64  		buf.WriteByte('(')
    65  		for i, arg := range args {
    66  			if i > 0 {
    67  				buf.WriteString(", ")
    68  			}
    69  			if arg.Name == "" {
    70  				panic("empty parameter/result name")
    71  			}
    72  			fmt.Fprintf(&buf, "%s %s", arg.Name, arg.Type)
    73  		}
    74  		buf.WriteByte(')')
    75  	}
    76  	if f.Recv.Type != nil {
    77  		fmt.Fprintf(&buf, "(%s %s) ", f.Recv.Name, f.Recv.Type)
    78  	}
    79  	buf.WriteString(f.Name)
    80  	argList(f.In, false)
    81  	if len(f.Out) > 0 {
    82  		buf.WriteByte(' ')
    83  		argList(f.Out, true)
    84  	}
    85  	return buf.String()
    86  }
    87  
    88  func (f *Func) Decl() string {
    89  	var buf strings.Builder
    90  	if f.Doc != "" {
    91  		for line := range strings.SplitSeq(strings.TrimRight(f.Doc, "\n"), "\n") {
    92  			fmt.Fprintf(&buf, "// %s\n", line)
    93  		}
    94  	}
    95  	buf.WriteString(f.Signature())
    96  	return buf.String()
    97  }
    98  
    99  // SpecFunc returns information about the spec package function that generated
   100  // f. name is the name of the function in the spec package, sig is its
   101  // uninstantiated signature type, and typeArgs is a slice of the type arguments
   102  // it was instantiated on to construct f.
   103  func (f *Func) SpecFunc() (name string, sig *types.Signature, typeArgs []types.Type) {
   104  	sFn := f.specFunc
   105  
   106  	// Build instantiated signature
   107  	for _, tparam := range sFn.TypeParams {
   108  		val := f.instance.Get(f.typeParamVars[tparam])
   109  		switch val := val.(type) {
   110  		case specexpr.Type:
   111  			typeArgs = append(typeArgs, specTypeToType(sFn.Pkg, val))
   112  		case specexpr.Num:
   113  			wt := sFn.Pkg.WidthTypes[val]
   114  			if wt == nil {
   115  				panic(fmt.Sprintf("no spec package type for width %s", val))
   116  			}
   117  			typeArgs = append(typeArgs, wt)
   118  		default:
   119  			panic("unexpected type parameter value")
   120  		}
   121  	}
   122  
   123  	return sFn.Name, sFn.Sig, typeArgs
   124  }
   125  

View as plain text