Source file src/simd/archsimd/_gen/sgutil/generic_ops.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 sgutil provides shared utilities for SIMD file
     6  // generation across architectures.  This includes
     7  //
     8  // - "natural" comparison for better ordering
     9  // - formatted-Go file saving
    10  // - generic ops file generation
    11  // - naming conventions and templates for the
    12  //   bitwise vector reinterpretation no-op methods.
    13  
    14  package sgutil
    15  
    16  import (
    17  	"fmt"
    18  	"io"
    19  	"sort"
    20  	"text/template"
    21  )
    22  
    23  const simdGenericOpsTmpl = `package main
    24  
    25  func init() {
    26  	additionalGenericOps["{{.ArchKey}}"] = []opData{
    27  {{- range .Ops }}
    28  		{name: "{{.OpName}}", argLength: {{.OpInLen}}{{if .Comm}}, commutative: true{{end}}{{if .HasAux}}, aux: "UInt8"{{end}}},
    29  {{- end }}
    30  	}
    31  }
    32  `
    33  
    34  // TemplateNamed returns a parsed template from temp, named name.
    35  func TemplateNamed(name, temp string) *template.Template {
    36  	t, err := template.New(name).Parse(temp)
    37  	if err != nil {
    38  		panic(fmt.Errorf("failed to parse template %s: %w", name, err))
    39  	}
    40  	return t
    41  }
    42  
    43  // GenericOpsData holds one generic op entry for template rendering.
    44  type GenericOpsData struct {
    45  	OpName  string
    46  	OpInLen int
    47  	Comm    bool
    48  	HasAux  bool
    49  }
    50  
    51  // WriteSIMDGenericOps generates the generic ops file content for archKey.
    52  func WriteSIMDGenericOps(w io.Writer, ops []GenericOpsData, archKey string) {
    53  	sort.Slice(ops, func(i, j int) bool {
    54  		return CompareNatural(ops[i].OpName, ops[j].OpName) < 0
    55  	})
    56  
    57  	var deduped []GenericOpsData
    58  	for _, op := range ops {
    59  		if len(deduped) > 0 && deduped[len(deduped)-1].OpName == op.OpName {
    60  			if deduped[len(deduped)-1].OpInLen != op.OpInLen ||
    61  				deduped[len(deduped)-1].Comm != op.Comm ||
    62  				deduped[len(deduped)-1].HasAux != op.HasAux {
    63  				panic(fmt.Sprintf("conflicting generic op definition for %s", op.OpName))
    64  			}
    65  			continue
    66  		}
    67  		deduped = append(deduped, op)
    68  	}
    69  
    70  	type templateData struct {
    71  		Header  string
    72  		ArchKey string
    73  		Ops     []GenericOpsData
    74  	}
    75  
    76  	t := TemplateNamed("simdgenericOps", simdGenericOpsTmpl)
    77  	err := t.Execute(w, templateData{
    78  		ArchKey: archKey,
    79  		Ops:     deduped,
    80  	})
    81  	if err != nil {
    82  		panic(fmt.Errorf("failed to execute template: %w", err))
    83  	}
    84  }
    85  

View as plain text