golang.org/x/arch@v0.17.0/internal/simdgen/godefs.go (about)

     1  // Copyright 2025 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 main
     6  
     7  import (
     8  	"fmt"
     9  	"io"
    10  	"log"
    11  
    12  	"golang.org/x/arch/internal/unify"
    13  )
    14  
    15  type Operation struct {
    16  	Go       string  // Go method name
    17  	Category *string // General operation category (optional)
    18  
    19  	GoArch string // GOARCH for this definition
    20  	Asm    string // Assembly mnemonic
    21  
    22  	In  []Operand // Arguments
    23  	Out []Operand // Results
    24  }
    25  
    26  type Operand struct {
    27  	Go     string // Go type of this operand
    28  	AsmPos int    // Position of this operand in the assembly instruction
    29  
    30  	Base string // Base Go type ("int", "uint", "float")
    31  	Bits int    // Element bit width
    32  	W    int    // Total vector bit width
    33  }
    34  
    35  func writeGoDefs(w io.Writer, cl unify.Closure) {
    36  	// TODO: Merge operations with the same signature but multiple
    37  	// implementations (e.g., SSE vs AVX)
    38  
    39  	// TODO: This code is embarrassing, but I'm very tired.
    40  
    41  	var op Operation
    42  	for def := range cl.All() {
    43  		if !def.Exact() {
    44  			continue
    45  		}
    46  		if err := def.Decode(&op); err != nil {
    47  			log.Println(err.Error())
    48  			continue
    49  		}
    50  
    51  		fmt.Fprintf(w, "func (x %s) %s(", op.In[0].Go, op.Go)
    52  		for i, arg := range op.In[1:] {
    53  			if i > 0 {
    54  				fmt.Fprint(w, ", ")
    55  			}
    56  			fmt.Fprintf(w, "%c %s", 'y'+i, arg.Go)
    57  		}
    58  		fmt.Fprintf(w, ") (")
    59  		for i, res := range op.Out {
    60  			if i > 0 {
    61  				fmt.Fprint(w, ", ")
    62  			}
    63  			fmt.Fprintf(w, "%c %s", 'o'+i, res.Go)
    64  		}
    65  		fmt.Fprintf(w, ") {\n")
    66  
    67  		asmPosToArg := make(map[int]byte)
    68  		asmPosToRes := make(map[int]byte)
    69  		for i, arg := range op.In {
    70  			asmPosToArg[arg.AsmPos] = 'x' + byte(i)
    71  		}
    72  		for i, res := range op.Out {
    73  			asmPosToRes[res.AsmPos] = 'o' + byte(i)
    74  		}
    75  		fmt.Fprintf(w, "\t// %s", op.Asm)
    76  		for i := 0; ; i++ {
    77  			arg, okArg := asmPosToArg[i]
    78  			if okArg {
    79  				fmt.Fprintf(w, " %c", arg)
    80  			}
    81  			res, okRes := asmPosToRes[i]
    82  			if okRes {
    83  				if okArg {
    84  					fmt.Fprintf(w, "/")
    85  				} else {
    86  					fmt.Fprintf(w, " ")
    87  				}
    88  				fmt.Fprintf(w, "%c", res)
    89  			}
    90  			if !okArg && !okRes {
    91  				break
    92  			}
    93  		}
    94  		fmt.Fprintf(w, "\n")
    95  
    96  		fmt.Fprintf(w, "}\n")
    97  	}
    98  }