// Package main is a code generator that creates functions of different size. package main import ( "fmt" "os" ) //go:generate go run . func main() { if err := run(); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } func run() error { file, err := os.Create("generated.go") if err != nil { return err } defer file.Close() fmt.Fprint(file, `// Code generated by go generate; DO NOT EDIT. package main //go:noinline func stackdepth1(fn func()) { fn() } `) max := 1024 for i := 2; i <= max; i++ { fmt.Fprintf( file, "//go:noinline\nfunc stackdepth%d(fn func()) { stackdepth%d(fn) }\n", i, i-1, ) } fmt.Fprint(file, "\nvar stackdepth = map[int]func(func()) {\n") for i := 1; i <= max; i++ { fmt.Fprintf(file, "\t%d: stackdepth%d,\n", i, i) } fmt.Fprint(file, "}\n") // Disabled: Turned out to be a deadend //for i := 1; i <= max; i *= 2 { //fmt.Fprintf(file, "//go:noinline\n") //fmt.Fprintf(file, "func funcsize%d(v0, n int, fn func()) int {\n", i) //for n := 1; n <= i; n++ { //fmt.Fprintf(file, "\tv%d := v%d\n", n, n-1) //fmt.Fprintf(file, "\tv%d = (^v%d + %d)\n", n, n, n) //fmt.Fprintf(file, "\tif v%d == 23 {\n", n) //sum := []string{} //for j := 0; j <= n; j++ { //sum = append(sum, fmt.Sprintf("v%d", j)) //} //fmt.Fprintf(file, "\t\treturn %s\n", strings.Join(sum, " + ")) //fmt.Fprintf(file, "\t}\n") //} //fmt.Fprintf(file, "\tfn()\n") //fmt.Fprintf(file, "\treturn -1\n") //fmt.Fprintf(file, "}\n\n") //} //fmt.Fprint(file, "\nvar funcsize = map[int]func(int, int, func()) int {\n") //for i := 1; i <= max; i *= 2 { //fmt.Fprintf(file, "\t%d: funcsize%d,\n", i, i) //} //fmt.Fprint(file, "}\n") return file.Close() }