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

View as plain text