Files

99 lines
2.0 KiB
Go
Raw Permalink Normal View History

2019-01-05 11:46:51 -08:00
// Command avogen generates code based on the instruction database.
2018-11-24 13:00:27 -08:00
package main
import (
"flag"
"fmt"
2018-11-24 13:00:27 -08:00
"go/build"
"log"
"os"
"path/filepath"
2026-03-06 20:14:02 +00:00
"sources.truenas.cloud/code/avo/internal/gen"
"sources.truenas.cloud/code/avo/internal/inst"
"sources.truenas.cloud/code/avo/internal/load"
"sources.truenas.cloud/code/avo/printer"
2018-11-24 13:00:27 -08:00
)
2018-11-24 13:47:30 -08:00
var generators = map[string]gen.Builder{
all: AVX-512 (#217) Extends avo to support most AVX-512 instruction sets. The instruction type is extended to support suffixes. The K family of opmask registers is added to the register package, and the operand package is updated to support the new operand types. Move instruction deduction in `Load` and `Store` is extended to support KMOV* and VMOV* forms. Internal code generation packages were overhauled. Instruction database loading required various messy changes to account for the additional complexities of the AVX-512 instruction sets. The internal/api package was added to introduce a separation between instruction forms in the database, and the functions avo provides to create them. This was required since with instruction suffixes there is no longer a one-to-one mapping between instruction constructors and opcodes. AVX-512 bloated generated source code size substantially, initially increasing compilation and CI test times to an unacceptable level. Two changes were made to address this: 1. Instruction constructors in the `x86` package moved to an optab-based approach. This compiles substantially faster than the verbose code generation we had before. 2. The most verbose code-generated tests are moved under build tags and limited to a stress test mode. Stress test builds are run on schedule but not in regular CI. An example of AVX-512 accelerated 16-lane MD5 is provided to demonstrate and test the new functionality. Updates #20 #163 #229 Co-authored-by: Vaughn Iverson <vsivsi@yahoo.com>
2021-11-12 18:35:36 -08:00
"asmtest": gen.NewAsmTest,
"godata": gen.NewGoData,
"godatatest": gen.NewGoDataTest,
"optab": gen.NewOptab,
"ctors": gen.NewCtors,
"ctorstest": gen.NewCtorsTest,
"ctorsstress": gen.NewCtorsStress,
"ctorsbench": gen.NewCtorsBench,
"build": gen.NewBuild,
"buildtest": gen.NewBuildTest,
"mov": gen.NewMOV,
2018-11-24 13:00:27 -08:00
}
2018-11-25 17:11:24 -08:00
// Command-line flags.
var (
bootstrap = flag.Bool("bootstrap", false, "regenerate instruction list from original data")
datadir = flag.String(
"data",
2026-03-06 20:14:02 +00:00
filepath.Join(build.Default.GOPATH, "src/sources.truenas.cloud/code/avo/internal/data"),
2018-11-25 17:11:24 -08:00
"path to data directory",
)
output = flag.String("output", "", "path to output file (default stdout)")
2018-11-24 13:00:27 -08:00
)
func main() {
2018-11-25 17:11:24 -08:00
log.SetPrefix("avogen: ")
log.SetFlags(0)
2018-11-24 13:00:27 -08:00
flag.Parse()
if err := run(); err != nil {
log.Fatal(err)
}
}
2018-11-24 13:00:27 -08:00
func run() error {
2018-11-24 13:00:27 -08:00
// Build generator.
t := flag.Arg(0)
2018-11-24 13:47:30 -08:00
builder := generators[t]
if builder == nil {
return fmt.Errorf("unknown generator type '%s'", t)
2018-11-24 13:00:27 -08:00
}
2018-12-18 22:57:26 -08:00
g := builder(printer.NewArgvConfig())
2018-11-24 13:47:30 -08:00
2018-11-24 13:00:27 -08:00
// Determine output writer.
w := os.Stdout
if *output != "" {
2018-11-24 13:47:30 -08:00
f, err := os.Create(*output)
2018-11-24 13:00:27 -08:00
if err != nil {
return err
2018-11-24 13:00:27 -08:00
}
2018-11-24 13:47:30 -08:00
defer f.Close()
2018-11-24 13:00:27 -08:00
w = f
}
// Load instructions.
2018-11-25 17:11:24 -08:00
is := inst.Instructions
if *bootstrap {
log.Printf("bootstrap: loading instructions from data directory %s", *datadir)
l := load.NewLoaderFromDataDir(*datadir)
r, err := l.Load()
if err != nil {
return err
2018-11-25 17:11:24 -08:00
}
is = r
2018-11-24 13:00:27 -08:00
}
// Generate output.
b, generr := g.Generate(is)
2018-11-24 13:00:27 -08:00
// Write.
if _, err := w.Write(b); err != nil {
return err
2018-11-24 13:00:27 -08:00
}
if generr != nil {
return generr
}
return nil
2018-11-24 13:00:27 -08:00
}