Source file src/simd/archsimd/_gen/cmd/specstats/main.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  // Specstats reports progress on the internal/spec transition described in
     6  // SPEC-TRANSITION.md. It prints the report to standard output:
     7  //
     8  //	go run ./cmd/specstats
     9  //
    10  // The report is not checked in. Nearly every figure in it is a total that
    11  // almost every spec or API change moves, so a checked-in copy made changes in
    12  // flight conflict with each other and went stale whenever someone forgot to
    13  // regenerate it. Run it at whatever commit you want numbers for. The figures
    14  // that must not regress are enforced by TestInvariants instead.
    15  //
    16  // Every figure it prints is a fraction heading for 100% or a defect count
    17  // heading for zero, tied to the tasks that move it. Anything that is merely
    18  // interesting, rather than a measure of how far along we are, does not belong
    19  // here.
    20  //
    21  // # How it is put together
    22  //
    23  // Almost every figure in the report is the same operation: count the distinct
    24  // things at some granularity, and count how many of them are done. So the
    25  // program builds one fact table -- [fact], a declaration as seen in one build
    26  // configuration -- and everything downstream is a pivot over it: pick a grain
    27  // ([fact.declKey], [fact.triple], [fact.pair], name), pick a predicate, and
    28  // optionally group by a dimension. [tally] does the counting and [pivot] does
    29  // the grouping, so a new figure is a few lines rather than a new loop.
    30  //
    31  // Like Fill, this parses rather than type-checks, so it sees every target's
    32  // declarations regardless of build tags (SPEC-TRANSITION.md ยง2.4). It is
    33  // mostly a measurement tool: it reports divergence and does not judge it. The
    34  // exception is the counts that have reached zero (see [invariant]), which
    35  // TestInvariants enforces. fill builds the checker, and should absorb the
    36  // comparison half of this program rather than leave two implementations to
    37  // drift.
    38  package main
    39  
    40  import (
    41  	"bytes"
    42  	"flag"
    43  	"log"
    44  	"os"
    45  	"path/filepath"
    46  
    47  	"simd/archsimd/_gen/gentools"
    48  	"simd/archsimd/_gen/specgen"
    49  )
    50  
    51  func main() {
    52  	log.SetFlags(0)
    53  	log.SetPrefix("specstats: ")
    54  	genOpts := gentools.RegisterFlags(nil)
    55  	flag.Parse()
    56  	if genOpts.Write || genOpts.Diff {
    57  		log.Fatal("the report is no longer checked in; run without -w or -diff to print it")
    58  	}
    59  
    60  	var buf bytes.Buffer
    61  	load(genOpts).report(&buf)
    62  	os.Stdout.Write(buf.Bytes())
    63  }
    64  
    65  // load reads spec and the simd and archsimd APIs and measures them.
    66  func load(genOpts *gentools.Options) *metrics {
    67  	specDir := specgen.MustFindSpecDir(genOpts.GOROOT)
    68  	simdDir := filepath.Clean(filepath.Join(specDir, "..", ".."))
    69  	genDir := filepath.Join(simdDir, "archsimd", "_gen")
    70  
    71  	spec, err := specgen.Load(specDir, nil)
    72  	if err != nil {
    73  		log.Fatalf("loading spec: %s", err)
    74  	}
    75  	return measure(loadAPI(genOpts, simdDir), spec, genDir)
    76  }
    77  

View as plain text