summaryrefslogtreecommitdiffhomepage
path: root/tools/go_stateify/main.go
diff options
context:
space:
mode:
authorAndrei Vagin <avagin@google.com>2020-03-06 21:12:32 -0800
committerGitHub <noreply@github.com>2020-03-06 21:12:32 -0800
commitbf87da89d3c43555fd57e8f1d7aed21b6da78de4 (patch)
tree744ba15a2f663d64d56bf1c70bdfe4096f6a1af9 /tools/go_stateify/main.go
parent89957c6c87b5ad5c7bac68f93d9472388db57702 (diff)
parentddfc7239be94fa9711df877a66a9718aabff8b96 (diff)
Merge branch 'master' into pr_lazy_fpsimd_2
Diffstat (limited to 'tools/go_stateify/main.go')
-rw-r--r--tools/go_stateify/main.go130
1 files changed, 15 insertions, 115 deletions
diff --git a/tools/go_stateify/main.go b/tools/go_stateify/main.go
index 7d5d291e6..3437aa476 100644
--- a/tools/go_stateify/main.go
+++ b/tools/go_stateify/main.go
@@ -22,126 +22,22 @@ import (
"go/ast"
"go/parser"
"go/token"
- "io/ioutil"
"os"
"path/filepath"
"reflect"
"strings"
"sync"
+
+ "gvisor.dev/gvisor/tools/tags"
)
var (
- pkg = flag.String("pkg", "", "output package")
+ fullPkg = flag.String("fullpkg", "", "fully qualified output package")
imports = flag.String("imports", "", "extra imports for the output file")
output = flag.String("output", "", "output file")
statePkg = flag.String("statepkg", "", "state import package; defaults to empty")
- arch = flag.String("arch", "", "specify the target platform")
)
-// The known architectures.
-var okgoarch = []string{
- "386",
- "amd64",
- "arm",
- "arm64",
- "mips",
- "mipsle",
- "mips64",
- "mips64le",
- "ppc64",
- "ppc64le",
- "riscv64",
- "s390x",
- "sparc64",
- "wasm",
-}
-
-// readfile returns the content of the named file.
-func readfile(file string) string {
- data, err := ioutil.ReadFile(file)
- if err != nil {
- panic(fmt.Sprintf("readfile err: %v", err))
- }
- return string(data)
-}
-
-// matchfield reports whether the field (x,y,z) matches this build.
-// all the elements in the field must be satisfied.
-func matchfield(f string, goarch string) bool {
- for _, tag := range strings.Split(f, ",") {
- if !matchtag(tag, goarch) {
- return false
- }
- }
- return true
-}
-
-// matchtag reports whether the tag (x or !x) matches this build.
-func matchtag(tag string, goarch string) bool {
- if tag == "" {
- return false
- }
- if tag[0] == '!' {
- if len(tag) == 1 || tag[1] == '!' {
- return false
- }
- return !matchtag(tag[1:], goarch)
- }
- return tag == goarch
-}
-
-// canBuild reports whether we can build this file for target platform by
-// checking file name and build tags. The code is derived from the Go source
-// cmd.dist.build.shouldbuild.
-func canBuild(file, goTargetArch string) bool {
- name := filepath.Base(file)
- excluded := func(list []string, ok string) bool {
- for _, x := range list {
- if x == ok || (ok == "android" && x == "linux") || (ok == "illumos" && x == "solaris") {
- continue
- }
- i := strings.Index(name, x)
- if i <= 0 || name[i-1] != '_' {
- continue
- }
- i += len(x)
- if i == len(name) || name[i] == '.' || name[i] == '_' {
- return true
- }
- }
- return false
- }
- if excluded(okgoarch, goTargetArch) {
- return false
- }
-
- // Check file contents for // +build lines.
- for _, p := range strings.Split(readfile(file), "\n") {
- p = strings.TrimSpace(p)
- if p == "" {
- continue
- }
- if !strings.HasPrefix(p, "//") {
- break
- }
- if !strings.Contains(p, "+build") {
- continue
- }
- fields := strings.Fields(p[2:])
- if len(fields) < 1 || fields[0] != "+build" {
- continue
- }
- for _, p := range fields[1:] {
- if matchfield(p, goTargetArch) {
- goto fieldmatch
- }
- }
- return false
- fieldmatch:
- }
- return true
-}
-
// resolveTypeName returns a qualified type name.
func resolveTypeName(name string, typ ast.Expr) (field string, qualified string) {
for done := false; !done; {
@@ -275,7 +171,7 @@ func main() {
flag.Usage()
os.Exit(1)
}
- if *pkg == "" {
+ if *fullPkg == "" {
fmt.Fprintf(os.Stderr, "Error: package required.")
os.Exit(1)
}
@@ -307,7 +203,7 @@ func main() {
// Declare our emission closures.
emitRegister := func(name string) {
- initCalls = append(initCalls, fmt.Sprintf("%sRegister(\"%s.%s\", (*%s)(nil), state.Fns{Save: (*%s).save, Load: (*%s).load})", statePrefix, *pkg, name, name, name, name))
+ initCalls = append(initCalls, fmt.Sprintf("%sRegister(\"%s.%s\", (*%s)(nil), state.Fns{Save: (*%s).save, Load: (*%s).load})", statePrefix, *fullPkg, name, name, name, name))
}
emitZeroCheck := func(name string) {
fmt.Fprintf(outputFile, " if !%sIsZeroValue(x.%s) { m.Failf(\"%s is %%v, expected zero\", x.%s) }\n", statePrefix, name, name, name)
@@ -329,9 +225,17 @@ func main() {
fmt.Fprintf(outputFile, " m.Save(\"%s\", &x.%s)\n", name, name)
}
- // Emit the package name.
+ // Automated warning.
fmt.Fprint(outputFile, "// automatically generated by stateify.\n\n")
- fmt.Fprintf(outputFile, "package %s\n\n", *pkg)
+
+ // Emit build tags.
+ if t := tags.Aggregate(flag.Args()); len(t) > 0 {
+ fmt.Fprintf(outputFile, "%s\n\n", strings.Join(t.Lines(), "\n"))
+ }
+
+ // Emit the package name.
+ _, pkg := filepath.Split(*fullPkg)
+ fmt.Fprintf(outputFile, "package %s\n\n", pkg)
// Emit the imports lazily.
var once sync.Once
@@ -364,10 +268,6 @@ func main() {
os.Exit(1)
}
- if !canBuild(filename, *arch) {
- continue
- }
-
files = append(files, f)
}