summaryrefslogtreecommitdiffhomepage
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/checkunsafe/BUILD13
-rw-r--r--tools/checkunsafe/check_unsafe.go56
-rwxr-xr-xtools/go_branch.sh94
-rw-r--r--tools/go_generics/BUILD38
-rw-r--r--tools/go_generics/defs.bzl140
-rw-r--r--tools/go_generics/generics.go284
-rw-r--r--tools/go_generics/generics_tests/all_stmts/input.go290
-rw-r--r--tools/go_generics/generics_tests/all_stmts/opts.txt1
-rw-r--r--tools/go_generics/generics_tests/all_stmts/output/output.go288
-rw-r--r--tools/go_generics/generics_tests/all_types/input.go43
-rw-r--r--tools/go_generics/generics_tests/all_types/lib/lib.go17
-rw-r--r--tools/go_generics/generics_tests/all_types/opts.txt1
-rw-r--r--tools/go_generics/generics_tests/all_types/output/output.go41
-rw-r--r--tools/go_generics/generics_tests/anon/input.go46
-rw-r--r--tools/go_generics/generics_tests/anon/opts.txt1
-rw-r--r--tools/go_generics/generics_tests/anon/output/output.go42
-rw-r--r--tools/go_generics/generics_tests/consts/input.go26
-rw-r--r--tools/go_generics/generics_tests/consts/opts.txt1
-rw-r--r--tools/go_generics/generics_tests/consts/output/output.go26
-rw-r--r--tools/go_generics/generics_tests/imports/input.go24
-rw-r--r--tools/go_generics/generics_tests/imports/opts.txt1
-rw-r--r--tools/go_generics/generics_tests/imports/output/output.go27
-rw-r--r--tools/go_generics/generics_tests/remove_typedef/input.go37
-rw-r--r--tools/go_generics/generics_tests/remove_typedef/opts.txt1
-rw-r--r--tools/go_generics/generics_tests/remove_typedef/output/output.go29
-rw-r--r--tools/go_generics/generics_tests/simple/input.go45
-rw-r--r--tools/go_generics/generics_tests/simple/opts.txt1
-rw-r--r--tools/go_generics/generics_tests/simple/output/output.go43
-rw-r--r--tools/go_generics/globals/BUILD13
-rw-r--r--tools/go_generics/globals/globals_visitor.go597
-rw-r--r--tools/go_generics/globals/scope.go80
-rwxr-xr-xtools/go_generics/go_generics_unittest.sh70
-rw-r--r--tools/go_generics/go_merge/BUILD9
-rw-r--r--tools/go_generics/go_merge/main.go139
-rw-r--r--tools/go_generics/imports.go150
-rw-r--r--tools/go_generics/remove.go105
-rw-r--r--tools/go_generics/rules_tests/BUILD43
-rw-r--r--tools/go_generics/rules_tests/template.go42
-rw-r--r--tools/go_generics/rules_tests/template_test.go48
-rw-r--r--tools/go_marshal/BUILD14
-rw-r--r--tools/go_marshal/README.md164
-rw-r--r--tools/go_marshal/analysis/BUILD13
-rw-r--r--tools/go_marshal/analysis/analysis_unsafe.go175
-rw-r--r--tools/go_marshal/defs.bzl152
-rw-r--r--tools/go_marshal/gomarshal/BUILD17
-rw-r--r--tools/go_marshal/gomarshal/generator.go382
-rw-r--r--tools/go_marshal/gomarshal/generator_interfaces.go507
-rw-r--r--tools/go_marshal/gomarshal/generator_tests.go154
-rw-r--r--tools/go_marshal/gomarshal/util.go387
-rw-r--r--tools/go_marshal/main.go73
-rw-r--r--tools/go_marshal/marshal/BUILD14
-rw-r--r--tools/go_marshal/marshal/marshal.go60
-rw-r--r--tools/go_marshal/test/BUILD30
-rw-r--r--tools/go_marshal/test/benchmark_test.go178
-rw-r--r--tools/go_marshal/test/external/BUILD11
-rw-r--r--tools/go_marshal/test/external/external.go23
-rw-r--r--tools/go_marshal/test/test.go105
-rw-r--r--tools/go_stateify/BUILD9
-rw-r--r--tools/go_stateify/defs.bzl136
-rw-r--r--tools/go_stateify/main.go418
-rwxr-xr-xtools/image_build.sh98
-rwxr-xr-xtools/make_repository.sh108
-rw-r--r--tools/nogo.js7
-rwxr-xr-xtools/tag_release.sh69
-rwxr-xr-xtools/workspace_status.sh18
65 files changed, 0 insertions, 6274 deletions
diff --git a/tools/checkunsafe/BUILD b/tools/checkunsafe/BUILD
deleted file mode 100644
index d85c56131..000000000
--- a/tools/checkunsafe/BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_tool_library")
-
-package(licenses = ["notice"])
-
-go_tool_library(
- name = "checkunsafe",
- srcs = ["check_unsafe.go"],
- importpath = "checkunsafe",
- visibility = ["//visibility:public"],
- deps = [
- "@org_golang_x_tools//go/analysis:go_tool_library",
- ],
-)
diff --git a/tools/checkunsafe/check_unsafe.go b/tools/checkunsafe/check_unsafe.go
deleted file mode 100644
index 4ccd7cc5a..000000000
--- a/tools/checkunsafe/check_unsafe.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package checkunsafe allows unsafe imports only in files named appropriately.
-package checkunsafe
-
-import (
- "fmt"
- "path"
- "strconv"
- "strings"
-
- "golang.org/x/tools/go/analysis"
-)
-
-// Analyzer defines the entrypoint.
-var Analyzer = &analysis.Analyzer{
- Name: "checkunsafe",
- Doc: "allows unsafe use only in specified files",
- Run: run,
-}
-
-func run(pass *analysis.Pass) (interface{}, error) {
- for _, f := range pass.Files {
- for _, imp := range f.Imports {
- // Is this an unsafe import?
- pkg, err := strconv.Unquote(imp.Path.Value)
- if err != nil || pkg != "unsafe" {
- continue
- }
-
- // Extract the filename.
- filename := pass.Fset.File(imp.Pos()).Name()
-
- // Allow files named _unsafe.go or _test.go to opt out.
- if strings.HasSuffix(filename, "_unsafe.go") || strings.HasSuffix(filename, "_test.go") {
- continue
- }
-
- // Throw the error.
- pass.Reportf(imp.Pos(), fmt.Sprintf("package unsafe imported by %s; must end with _unsafe.go", path.Base(filename)))
- }
- }
- return nil, nil
-}
diff --git a/tools/go_branch.sh b/tools/go_branch.sh
deleted file mode 100755
index 0ac16e266..000000000
--- a/tools/go_branch.sh
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/bash
-
-# Copyright 2019 The gVisor Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -eo pipefail
-
-# Discovery the package name from the go.mod file.
-declare -r module=$(cat go.mod | grep -E "^module" | cut -d' ' -f2)
-declare -r origpwd=$(pwd)
-declare -r othersrc=("go.mod" "go.sum" "AUTHORS" "LICENSE")
-
-# Check that gopath has been built.
-declare -r gopath_dir="$(pwd)/bazel-bin/gopath/src/${module}"
-if ! [ -d "${gopath_dir}" ]; then
- echo "No gopath directory found; build the :gopath target." >&2
- exit 1
-fi
-
-# Create a temporary working directory, and ensure that this directory and all
-# subdirectories are cleaned up upon exit.
-declare -r tmp_dir=$(mktemp -d)
-finish() {
- cd # Leave tmp_dir.
- rm -rf "${tmp_dir}"
-}
-trap finish EXIT
-
-# Record the current working commit.
-declare -r head=$(git describe --always)
-
-# We expect to have an existing go branch that we will use as the basis for
-# this commit. That branch may be empty, but it must exist.
-declare -r go_branch=$(git show-ref --hash origin/go)
-
-# Clone the current repository to the temporary directory, and check out the
-# current go_branch directory. We move to the new repository for convenience.
-declare -r repo_orig="$(pwd)"
-declare -r repo_new="${tmp_dir}/repository"
-git clone . "${repo_new}"
-cd "${repo_new}"
-
-# Setup the repository and checkout the branch.
-git config user.email "gvisor-bot@google.com"
-git config user.name "gVisor bot"
-git fetch origin "${go_branch}"
-git checkout -b go "${go_branch}"
-
-# Start working on a merge commit that combines the previous history with the
-# current history. Note that we don't actually want any changes yet.
-#
-# N.B. The git behavior changed at some point and the relevant flag was added
-# to allow for override, so try the only behavior first then pass the flag.
-git merge --no-commit --strategy ours ${head} || \
- git merge --allow-unrelated-histories --no-commit --strategy ours ${head}
-
-# Sync the entire gopath_dir.
-rsync --recursive --verbose --delete --exclude .git -L "${gopath_dir}/" .
-
-# Add additional files.
-for file in "${othersrc[@]}"; do
- cp "${origpwd}"/"${file}" .
-done
-
-# Construct a new README.md.
-cat > README.md <<EOF
-# gVisor
-
-This branch is a synthetic branch, containing only Go sources, that is
-compatible with standard Go tools. See the `master` branch for authoritative
-sources and tests.
-EOF
-
-# There are a few solitary files that can get left behind due to the way bazel
-# constructs the gopath target. Note that we don't find all Go files here
-# because they may correspond to unused templates, etc.
-cp "${repo_orig}"/runsc/*.go runsc/
-
-# Update the current working set and commit.
-git add . && git commit -m "Merge ${head} (automated)"
-
-# Push the branch back to the original repository.
-git remote add orig "${repo_orig}" && git push -f orig go:go
diff --git a/tools/go_generics/BUILD b/tools/go_generics/BUILD
deleted file mode 100644
index 39318b877..000000000
--- a/tools/go_generics/BUILD
+++ /dev/null
@@ -1,38 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary")
-
-package(licenses = ["notice"])
-
-go_binary(
- name = "go_generics",
- srcs = [
- "generics.go",
- "imports.go",
- "remove.go",
- ],
- visibility = ["//visibility:public"],
- deps = ["//tools/go_generics/globals"],
-)
-
-genrule(
- name = "go_generics_tests",
- srcs = glob(["generics_tests/**"]) + [":go_generics"],
- outs = ["go_generics_tests.tgz"],
- cmd = "tar -czvhf $@ $(SRCS)",
-)
-
-genrule(
- name = "go_generics_test_bundle",
- srcs = [
- ":go_generics_tests.tgz",
- ":go_generics_unittest.sh",
- ],
- outs = ["go_generics_test.sh"],
- cmd = "cat $(location :go_generics_unittest.sh) $(location :go_generics_tests.tgz) > $@",
- executable = True,
-)
-
-sh_test(
- name = "go_generics_test",
- size = "small",
- srcs = ["go_generics_test.sh"],
-)
diff --git a/tools/go_generics/defs.bzl b/tools/go_generics/defs.bzl
deleted file mode 100644
index c5be52ecd..000000000
--- a/tools/go_generics/defs.bzl
+++ /dev/null
@@ -1,140 +0,0 @@
-def _go_template_impl(ctx):
- input = ctx.files.srcs
- output = ctx.outputs.out
-
- args = ["-o=%s" % output.path] + [f.path for f in input]
-
- ctx.actions.run(
- inputs = input,
- outputs = [output],
- mnemonic = "GoGenericsTemplate",
- progress_message = "Building Go template %s" % ctx.label,
- arguments = args,
- executable = ctx.executable._tool,
- )
-
- return struct(
- types = ctx.attr.types,
- opt_types = ctx.attr.opt_types,
- consts = ctx.attr.consts,
- opt_consts = ctx.attr.opt_consts,
- deps = ctx.attr.deps,
- file = output,
- )
-
-"""
-Generates a Go template from a set of Go files.
-
-A Go template is similar to a go library, except that it has certain types that
-can be replaced before usage. For example, one could define a templatized List
-struct, whose elements are of type T, then instantiate that template for
-T=segment, where "segment" is the concrete type.
-
-Args:
- name: the name of the template.
- srcs: the list of source files that comprise the template.
- types: the list of generic types in the template that are required to be specified.
- opt_types: the list of generic types in the template that can but aren't required to be specified.
- consts: the list of constants in the template that are required to be specified.
- opt_consts: the list of constants in the template that can but aren't required to be specified.
- deps: the list of dependencies.
-"""
-go_template = rule(
- implementation = _go_template_impl,
- attrs = {
- "srcs": attr.label_list(mandatory = True, allow_files = True),
- "deps": attr.label_list(allow_files = True),
- "types": attr.string_list(),
- "opt_types": attr.string_list(),
- "consts": attr.string_list(),
- "opt_consts": attr.string_list(),
- "_tool": attr.label(executable = True, cfg = "host", default = Label("//tools/go_generics/go_merge")),
- },
- outputs = {
- "out": "%{name}_template.go",
- },
-)
-
-def _go_template_instance_impl(ctx):
- template = ctx.attr.template
- output = ctx.outputs.out
-
- # Check that all required types are defined.
- for t in template.types:
- if t not in ctx.attr.types:
- fail("Missing value for type %s in %s" % (t, ctx.attr.template.label))
-
- # Check that all defined types are expected by the template.
- for t in ctx.attr.types:
- if (t not in template.types) and (t not in template.opt_types):
- fail("Type %s it not a parameter to %s" % (t, ctx.attr.template.label))
-
- # Check that all required consts are defined.
- for t in template.consts:
- if t not in ctx.attr.consts:
- fail("Missing value for constant %s in %s" % (t, ctx.attr.template.label))
-
- # Check that all defined consts are expected by the template.
- for t in ctx.attr.consts:
- if (t not in template.consts) and (t not in template.opt_consts):
- fail("Const %s it not a parameter to %s" % (t, ctx.attr.template.label))
-
- # Build the argument list.
- args = ["-i=%s" % template.file.path, "-o=%s" % output.path]
- args += ["-p=%s" % ctx.attr.package]
-
- if len(ctx.attr.prefix) > 0:
- args += ["-prefix=%s" % ctx.attr.prefix]
-
- if len(ctx.attr.suffix) > 0:
- args += ["-suffix=%s" % ctx.attr.suffix]
-
- args += [("-t=%s=%s" % (p[0], p[1])) for p in ctx.attr.types.items()]
- args += [("-c=%s=%s" % (p[0], p[1])) for p in ctx.attr.consts.items()]
- args += [("-import=%s=%s" % (p[0], p[1])) for p in ctx.attr.imports.items()]
-
- if ctx.attr.anon:
- args += ["-anon"]
-
- ctx.actions.run(
- inputs = [template.file],
- outputs = [output],
- mnemonic = "GoGenericsInstance",
- progress_message = "Building Go template instance %s" % ctx.label,
- arguments = args,
- executable = ctx.executable._tool,
- )
-
- # TODO: How can we get the dependencies out?
- return struct(
- files = depset([output]),
- )
-
-"""
-Instantiates a Go template by replacing all generic types with concrete ones.
-
-Args:
- name: the name of the template instance.
- template: the label of the template to be instatiated.
- prefix: a prefix to be added to globals in the template.
- suffix: a suffix to be added to global in the template.
- types: the map from generic type names to concrete ones.
- consts: the map from constant names to their values.
- imports: the map from imports used in types/consts to their import paths.
- package: the name of the package the instantiated template will be compiled into.
-"""
-go_template_instance = rule(
- implementation = _go_template_instance_impl,
- attrs = {
- "template": attr.label(mandatory = True, providers = ["types"]),
- "prefix": attr.string(),
- "suffix": attr.string(),
- "types": attr.string_dict(),
- "consts": attr.string_dict(),
- "imports": attr.string_dict(),
- "anon": attr.bool(mandatory = False, default = False),
- "package": attr.string(mandatory = True),
- "out": attr.output(mandatory = True),
- "_tool": attr.label(executable = True, cfg = "host", default = Label("//tools/go_generics")),
- },
-)
diff --git a/tools/go_generics/generics.go b/tools/go_generics/generics.go
deleted file mode 100644
index e9cc2c753..000000000
--- a/tools/go_generics/generics.go
+++ /dev/null
@@ -1,284 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// go_generics reads a Go source file and writes a new version of that file with
-// a few transformations applied to each. Namely:
-//
-// 1. Global types can be explicitly renamed with the -t option. For example,
-// if -t=A=B is passed in, all references to A will be replaced with
-// references to B; a function declaration like:
-//
-// func f(arg *A)
-//
-// would be renamed to:
-//
-// func f(arg *B)
-//
-// 2. Global type definitions and their method sets will be removed when they're
-// being renamed with -t. For example, if -t=A=B is passed in, the following
-// definition and methods that existed in the input file wouldn't exist at
-// all in the output file:
-//
-// type A struct{}
-//
-// func (*A) f() {}
-//
-// 3. All global types, variables, constants and functions (not methods) are
-// prefixed and suffixed based on the option -prefix and -suffix arguments.
-// For example, if -suffix=A is passed in, the following globals:
-//
-// func f()
-// type t struct{}
-//
-// would be renamed to:
-//
-// func fA()
-// type tA struct{}
-//
-// Some special tags are also modified. For example:
-//
-// "state:.(t)"
-//
-// would become:
-//
-// "state:.(tA)"
-//
-// 4. The package is renamed to the value via the -p argument.
-// 5. Value of constants can be modified with -c argument.
-//
-// Note that not just the top-level declarations are renamed, all references to
-// them are also properly renamed as well, taking into account visibility rules
-// and shadowing. For example, if -suffix=A is passed in, the following:
-//
-// var b = 100
-//
-// func f() {
-// g(b)
-// b := 0
-// g(b)
-// }
-//
-// Would be replaced with:
-//
-// var bA = 100
-//
-// func f() {
-// g(bA)
-// b := 0
-// g(b)
-// }
-//
-// Note that the second call to g() kept "b" as an argument because it refers to
-// the local variable "b".
-//
-// Note that go_generics can handle anonymous fields with renamed types if
-// -anon is passed in, however it does not perform strict checking on parameter
-// types that share the same name as the global type and therefore will rename
-// them as well.
-//
-// You can see an example in the tools/go_generics/generics_tests/interface test.
-package main
-
-import (
- "bytes"
- "flag"
- "fmt"
- "go/ast"
- "go/format"
- "go/parser"
- "go/token"
- "io/ioutil"
- "os"
- "regexp"
- "strings"
-
- "gvisor.dev/gvisor/tools/go_generics/globals"
-)
-
-var (
- input = flag.String("i", "", "input `file`")
- output = flag.String("o", "", "output `file`")
- suffix = flag.String("suffix", "", "`suffix` to add to each global symbol")
- prefix = flag.String("prefix", "", "`prefix` to add to each global symbol")
- packageName = flag.String("p", "main", "output package `name`")
- printAST = flag.Bool("ast", false, "prints the AST")
- processAnon = flag.Bool("anon", false, "process anonymous fields")
- types = make(mapValue)
- consts = make(mapValue)
- imports = make(mapValue)
-)
-
-// mapValue implements flag.Value. We use a mapValue flag instead of a regular
-// string flag when we want to allow more than one instance of the flag. For
-// example, we allow several "-t A=B" arguments, and will rename them all.
-type mapValue map[string]string
-
-func (m mapValue) String() string {
- var b bytes.Buffer
- first := true
- for k, v := range m {
- if !first {
- b.WriteRune(',')
- } else {
- first = false
- }
- b.WriteString(k)
- b.WriteRune('=')
- b.WriteString(v)
- }
- return b.String()
-}
-
-func (m mapValue) Set(s string) error {
- sep := strings.Index(s, "=")
- if sep == -1 {
- return fmt.Errorf("missing '=' from '%s'", s)
- }
-
- m[s[:sep]] = s[sep+1:]
-
- return nil
-}
-
-// stateTagRegexp matches against the 'typed' state tags.
-var stateTagRegexp = regexp.MustCompile(`^(.*[^a-z0-9_])state:"\.\(([^\)]*)\)"(.*)$`)
-
-var identifierRegexp = regexp.MustCompile(`^(.*[^a-zA-Z_])([a-zA-Z_][a-zA-Z0-9_]*)(.*)$`)
-
-func main() {
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, "Usage: %s [options]\n", os.Args[0])
- flag.PrintDefaults()
- }
-
- flag.Var(types, "t", "rename type A to B when `A=B` is passed in. Multiple such mappings are allowed.")
- flag.Var(consts, "c", "reassign constant A to value B when `A=B` is passed in. Multiple such mappings are allowed.")
- flag.Var(imports, "import", "specifies the import libraries to use when types are not local. `name=path` specifies that 'name', used in types as name.type, refers to the package living in 'path'.")
- flag.Parse()
-
- if *input == "" || *output == "" {
- flag.Usage()
- os.Exit(1)
- }
-
- // Parse the input file.
- fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, *input, nil, parser.ParseComments|parser.DeclarationErrors|parser.SpuriousErrors)
- if err != nil {
- fmt.Fprintf(os.Stderr, "%v\n", err)
- os.Exit(1)
- }
-
- // Print the AST if requested.
- if *printAST {
- ast.Print(fset, f)
- }
-
- cmap := ast.NewCommentMap(fset, f, f.Comments)
-
- // Update imports based on what's used in types and consts.
- maps := []mapValue{types, consts}
- importDecl, err := updateImports(maps, imports)
- if err != nil {
- fmt.Fprintf(os.Stderr, "%v\n", err)
- os.Exit(1)
- }
- types = maps[0]
- consts = maps[1]
-
- // Reassign all specified constants.
- for _, decl := range f.Decls {
- d, ok := decl.(*ast.GenDecl)
- if !ok || d.Tok != token.CONST {
- continue
- }
-
- for _, gs := range d.Specs {
- s := gs.(*ast.ValueSpec)
- for i, id := range s.Names {
- if n, ok := consts[id.Name]; ok {
- s.Values[i] = &ast.BasicLit{Value: n}
- }
- }
- }
- }
-
- // Go through all globals and their uses in the AST and rename the types
- // with explicitly provided names, and rename all types, variables,
- // consts and functions with the provided prefix and suffix.
- globals.Visit(fset, f, func(ident *ast.Ident, kind globals.SymKind) {
- if n, ok := types[ident.Name]; ok && kind == globals.KindType {
- ident.Name = n
- } else {
- switch kind {
- case globals.KindType, globals.KindVar, globals.KindConst, globals.KindFunction:
- ident.Name = *prefix + ident.Name + *suffix
- case globals.KindTag:
- // Modify the state tag appropriately.
- if m := stateTagRegexp.FindStringSubmatch(ident.Name); m != nil {
- if t := identifierRegexp.FindStringSubmatch(m[2]); t != nil {
- typeName := *prefix + t[2] + *suffix
- if n, ok := types[t[2]]; ok {
- typeName = n
- }
- ident.Name = m[1] + `state:".(` + t[1] + typeName + t[3] + `)"` + m[3]
- }
- }
- }
- }
- }, *processAnon)
-
- // Remove the definition of all types that are being remapped.
- set := make(typeSet)
- for _, v := range types {
- set[v] = struct{}{}
- }
- removeTypes(set, f)
-
- // Add the new imports, if any, to the top.
- if importDecl != nil {
- newDecls := make([]ast.Decl, 0, len(f.Decls)+1)
- newDecls = append(newDecls, importDecl)
- newDecls = append(newDecls, f.Decls...)
- f.Decls = newDecls
- }
-
- // Update comments to remove the ones potentially associated with the
- // type T that we removed.
- f.Comments = cmap.Filter(f).Comments()
-
- // If there are file (package) comments, delete them.
- if f.Doc != nil {
- for i, cg := range f.Comments {
- if cg == f.Doc {
- f.Comments = append(f.Comments[:i], f.Comments[i+1:]...)
- break
- }
- }
- }
-
- // Write the output file.
- f.Name.Name = *packageName
-
- var buf bytes.Buffer
- if err := format.Node(&buf, fset, f); err != nil {
- fmt.Fprintf(os.Stderr, "%v\n", err)
- os.Exit(1)
- }
-
- if err := ioutil.WriteFile(*output, buf.Bytes(), 0644); err != nil {
- fmt.Fprintf(os.Stderr, "%v\n", err)
- os.Exit(1)
- }
-}
diff --git a/tools/go_generics/generics_tests/all_stmts/input.go b/tools/go_generics/generics_tests/all_stmts/input.go
deleted file mode 100644
index 4791d1ff1..000000000
--- a/tools/go_generics/generics_tests/all_stmts/input.go
+++ /dev/null
@@ -1,290 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tests
-
-import (
- "sync"
-)
-
-type T int
-
-func h(T) {
-}
-
-type s struct {
- a, b int
- c []int
-}
-
-func g(T) *s {
- return &s{}
-}
-
-func f() (T, []int) {
- // Branch.
- goto T
- goto R
-
- // Labeled.
-T:
- _ = T(0)
-
- // Empty.
-R:
- ;
-
- // Assignment with definition.
- a, b, c := T(1), T(2), T(3)
- _, _, _ = a, b, c
-
- // Assignment without definition.
- g(T(0)).a, g(T(1)).b, c = int(T(1)), int(T(2)), T(3)
- _, _, _ = a, b, c
-
- // Block.
- {
- var T T
- T = 0
- _ = T
- }
-
- // Declarations.
- type Type T
- const Const T = 10
- var g1 func(T, int, ...T) (int, T)
- var v T
- var w = T(0)
- {
- var T struct {
- f []T
- }
- _ = T
- }
-
- // Defer.
- defer g1(T(0), 1)
-
- // Expression.
- h(v + w + T(1))
-
- // For statements.
- for i := T(0); i < T(10); i++ {
- var T func(int) T
- v := T(0)
- _ = v
- }
-
- for {
- var T func(int) T
- v := T(0)
- _ = v
- }
-
- // Go.
- go g1(T(0), 1)
-
- // If statements.
- if a != T(1) {
- var T func(int) T
- v := T(0)
- _ = v
- }
-
- if a := T(0); a != T(1) {
- var T func(int) T
- v := T(0)
- _ = v
- }
-
- if a := T(0); a != T(1) {
- var T func(int) T
- v := T(0)
- _ = v
- } else if b := T(0); b != T(1) {
- var T func(int) T
- v := T(0)
- _ = v
- } else if T := T(0); T != 1 {
- T++
- } else {
- T--
- }
-
- if a := T(0); a != T(1) {
- var T func(int) T
- v := T(0)
- _ = v
- } else {
- var T func(int) T
- v := T(0)
- _ = v
- }
-
- // Inc/Dec statements.
- (*(*T)(nil))++
- (*(*T)(nil))--
-
- // Range statements.
- for g(T(0)).a, g(T(1)).b = range g(T(10)).c {
- var d T
- _ = d
- }
-
- for T, b := range g(T(10)).c {
- _ = T
- _ = b
- }
-
- // Select statement.
- {
- var fch func(T) chan int
-
- select {
- case <-fch(T(30)):
- var T T
- T = 0
- _ = T
- default:
- var T T
- T = 0
- _ = T
- case T := <-fch(T(30)):
- T = 0
- _ = T
- case g(T(0)).a = <-fch(T(30)):
- var T T
- T = 0
- _ = T
- case fch(T(30)) <- int(T(0)):
- var T T
- T = 0
- _ = T
- }
- }
-
- // Send statements.
- {
- var ch chan T
- var fch func(T) chan int
-
- ch <- T(0)
- fch(T(1)) <- g(T(10)).a
- }
-
- // Switch statements.
- {
- var a T
- var b int
- switch {
- case a == T(0):
- var T T
- T = 0
- _ = T
- case a < T(0), b < g(T(10)).a:
- var T T
- T = 0
- _ = T
- default:
- var T T
- T = 0
- _ = T
- }
- }
-
- switch T(g(T(10)).a) {
- case T(0):
- var T T
- T = 0
- _ = T
- case T(1), T(g(T(10)).a):
- var T T
- T = 0
- _ = T
- default:
- var T T
- T = 0
- _ = T
- }
-
- switch b := g(T(10)); T(b.a) + T(10) {
- case T(0):
- var T T
- T = 0
- _ = T
- case T(1), T(g(T(10)).a):
- var T T
- T = 0
- _ = T
- default:
- var T T
- T = 0
- _ = T
- }
-
- // Type switch statements.
- {
- var interfaceFunc func(T) interface{}
-
- switch interfaceFunc(T(0)).(type) {
- case *T, T, int:
- var T T
- T = 0
- _ = T
- case sync.Mutex, **T:
- var T T
- T = 0
- _ = T
- default:
- var T T
- T = 0
- _ = T
- }
-
- switch x := interfaceFunc(T(0)).(type) {
- case *T, T, int:
- var T T
- T = 0
- _ = T
- _ = x
- case sync.Mutex, **T:
- var T T
- T = 0
- _ = T
- default:
- var T T
- T = 0
- _ = T
- }
-
- switch t := T(0); x := interfaceFunc(T(0) + t).(type) {
- case *T, T, int:
- var T T
- T = 0
- _ = T
- _ = x
- case sync.Mutex, **T:
- var T T
- T = 0
- _ = T
- default:
- var T T
- T = 0
- _ = T
- }
- }
-
- // Return statement.
- return T(10), g(T(11)).c
-}
diff --git a/tools/go_generics/generics_tests/all_stmts/opts.txt b/tools/go_generics/generics_tests/all_stmts/opts.txt
deleted file mode 100644
index c9d0e09bf..000000000
--- a/tools/go_generics/generics_tests/all_stmts/opts.txt
+++ /dev/null
@@ -1 +0,0 @@
--t=T=Q
diff --git a/tools/go_generics/generics_tests/all_stmts/output/output.go b/tools/go_generics/generics_tests/all_stmts/output/output.go
deleted file mode 100644
index a53d84535..000000000
--- a/tools/go_generics/generics_tests/all_stmts/output/output.go
+++ /dev/null
@@ -1,288 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "sync"
-)
-
-func h(Q) {
-}
-
-type s struct {
- a, b int
- c []int
-}
-
-func g(Q) *s {
- return &s{}
-}
-
-func f() (Q, []int) {
- // Branch.
- goto T
- goto R
-
- // Labeled.
-T:
- _ = Q(0)
-
- // Empty.
-R:
- ;
-
- // Assignment with definition.
- a, b, c := Q(1), Q(2), Q(3)
- _, _, _ = a, b, c
-
- // Assignment without definition.
- g(Q(0)).a, g(Q(1)).b, c = int(Q(1)), int(Q(2)), Q(3)
- _, _, _ = a, b, c
-
- // Block.
- {
- var T Q
- T = 0
- _ = T
- }
-
- // Declarations.
- type Type Q
- const Const Q = 10
- var g1 func(Q, int, ...Q) (int, Q)
- var v Q
- var w = Q(0)
- {
- var T struct {
- f []Q
- }
- _ = T
- }
-
- // Defer.
- defer g1(Q(0), 1)
-
- // Expression.
- h(v + w + Q(1))
-
- // For statements.
- for i := Q(0); i < Q(10); i++ {
- var T func(int) Q
- v := T(0)
- _ = v
- }
-
- for {
- var T func(int) Q
- v := T(0)
- _ = v
- }
-
- // Go.
- go g1(Q(0), 1)
-
- // If statements.
- if a != Q(1) {
- var T func(int) Q
- v := T(0)
- _ = v
- }
-
- if a := Q(0); a != Q(1) {
- var T func(int) Q
- v := T(0)
- _ = v
- }
-
- if a := Q(0); a != Q(1) {
- var T func(int) Q
- v := T(0)
- _ = v
- } else if b := Q(0); b != Q(1) {
- var T func(int) Q
- v := T(0)
- _ = v
- } else if T := Q(0); T != 1 {
- T++
- } else {
- T--
- }
-
- if a := Q(0); a != Q(1) {
- var T func(int) Q
- v := T(0)
- _ = v
- } else {
- var T func(int) Q
- v := T(0)
- _ = v
- }
-
- // Inc/Dec statements.
- (*(*Q)(nil))++
- (*(*Q)(nil))--
-
- // Range statements.
- for g(Q(0)).a, g(Q(1)).b = range g(Q(10)).c {
- var d Q
- _ = d
- }
-
- for T, b := range g(Q(10)).c {
- _ = T
- _ = b
- }
-
- // Select statement.
- {
- var fch func(Q) chan int
-
- select {
- case <-fch(Q(30)):
- var T Q
- T = 0
- _ = T
- default:
- var T Q
- T = 0
- _ = T
- case T := <-fch(Q(30)):
- T = 0
- _ = T
- case g(Q(0)).a = <-fch(Q(30)):
- var T Q
- T = 0
- _ = T
- case fch(Q(30)) <- int(Q(0)):
- var T Q
- T = 0
- _ = T
- }
- }
-
- // Send statements.
- {
- var ch chan Q
- var fch func(Q) chan int
-
- ch <- Q(0)
- fch(Q(1)) <- g(Q(10)).a
- }
-
- // Switch statements.
- {
- var a Q
- var b int
- switch {
- case a == Q(0):
- var T Q
- T = 0
- _ = T
- case a < Q(0), b < g(Q(10)).a:
- var T Q
- T = 0
- _ = T
- default:
- var T Q
- T = 0
- _ = T
- }
- }
-
- switch Q(g(Q(10)).a) {
- case Q(0):
- var T Q
- T = 0
- _ = T
- case Q(1), Q(g(Q(10)).a):
- var T Q
- T = 0
- _ = T
- default:
- var T Q
- T = 0
- _ = T
- }
-
- switch b := g(Q(10)); Q(b.a) + Q(10) {
- case Q(0):
- var T Q
- T = 0
- _ = T
- case Q(1), Q(g(Q(10)).a):
- var T Q
- T = 0
- _ = T
- default:
- var T Q
- T = 0
- _ = T
- }
-
- // Type switch statements.
- {
- var interfaceFunc func(Q) interface{}
-
- switch interfaceFunc(Q(0)).(type) {
- case *Q, Q, int:
- var T Q
- T = 0
- _ = T
- case sync.Mutex, **Q:
- var T Q
- T = 0
- _ = T
- default:
- var T Q
- T = 0
- _ = T
- }
-
- switch x := interfaceFunc(Q(0)).(type) {
- case *Q, Q, int:
- var T Q
- T = 0
- _ = T
- _ = x
- case sync.Mutex, **Q:
- var T Q
- T = 0
- _ = T
- default:
- var T Q
- T = 0
- _ = T
- }
-
- switch t := Q(0); x := interfaceFunc(Q(0) + t).(type) {
- case *Q, Q, int:
- var T Q
- T = 0
- _ = T
- _ = x
- case sync.Mutex, **Q:
- var T Q
- T = 0
- _ = T
- default:
- var T Q
- T = 0
- _ = T
- }
- }
-
- // Return statement.
- return Q(10), g(Q(11)).c
-}
diff --git a/tools/go_generics/generics_tests/all_types/input.go b/tools/go_generics/generics_tests/all_types/input.go
deleted file mode 100644
index 3575d02ec..000000000
--- a/tools/go_generics/generics_tests/all_types/input.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tests
-
-import "./lib"
-
-type T int
-
-type newType struct {
- a T
- b lib.T
- c *T
- d (T)
- e chan T
- f <-chan T
- g chan<- T
- h []T
- i [10]T
- j map[T]T
- k func(T, T) (T, T)
- l interface {
- f(T)
- }
- m struct {
- T
- a T
- }
-}
-
-func f(...T) {
-}
diff --git a/tools/go_generics/generics_tests/all_types/lib/lib.go b/tools/go_generics/generics_tests/all_types/lib/lib.go
deleted file mode 100644
index 988786496..000000000
--- a/tools/go_generics/generics_tests/all_types/lib/lib.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package lib
-
-type T int32
diff --git a/tools/go_generics/generics_tests/all_types/opts.txt b/tools/go_generics/generics_tests/all_types/opts.txt
deleted file mode 100644
index c9d0e09bf..000000000
--- a/tools/go_generics/generics_tests/all_types/opts.txt
+++ /dev/null
@@ -1 +0,0 @@
--t=T=Q
diff --git a/tools/go_generics/generics_tests/all_types/output/output.go b/tools/go_generics/generics_tests/all_types/output/output.go
deleted file mode 100644
index 41fd147a1..000000000
--- a/tools/go_generics/generics_tests/all_types/output/output.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import "./lib"
-
-type newType struct {
- a Q
- b lib.T
- c *Q
- d (Q)
- e chan Q
- f <-chan Q
- g chan<- Q
- h []Q
- i [10]Q
- j map[Q]Q
- k func(Q, Q) (Q, Q)
- l interface {
- f(Q)
- }
- m struct {
- Q
- a Q
- }
-}
-
-func f(...Q) {
-}
diff --git a/tools/go_generics/generics_tests/anon/input.go b/tools/go_generics/generics_tests/anon/input.go
deleted file mode 100644
index 44086d522..000000000
--- a/tools/go_generics/generics_tests/anon/input.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tests
-
-type T interface {
- Apply(T) T
-}
-
-type Foo struct {
- T
- Bar map[string]T `json:"bar,omitempty"`
-}
-
-type Baz struct {
- T someTypeNotT
-}
-
-func (f Foo) GetBar(name string) T {
- b, ok := f.Bar[name]
- if ok {
- b = f.Apply(b)
- } else {
- b = f.T
- }
- return b
-}
-
-func foobar() {
- a := Baz{}
- a.T = 0 // should not be renamed, this is a limitation
-
- b := otherpkg.UnrelatedType{}
- b.T = 0 // should not be renamed, this is a limitation
-}
diff --git a/tools/go_generics/generics_tests/anon/opts.txt b/tools/go_generics/generics_tests/anon/opts.txt
deleted file mode 100644
index a5e9d26de..000000000
--- a/tools/go_generics/generics_tests/anon/opts.txt
+++ /dev/null
@@ -1 +0,0 @@
--t=T=Q -suffix=New -anon
diff --git a/tools/go_generics/generics_tests/anon/output/output.go b/tools/go_generics/generics_tests/anon/output/output.go
deleted file mode 100644
index 160cddf79..000000000
--- a/tools/go_generics/generics_tests/anon/output/output.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-type FooNew struct {
- Q
- Bar map[string]Q `json:"bar,omitempty"`
-}
-
-type BazNew struct {
- T someTypeNotT
-}
-
-func (f FooNew) GetBar(name string) Q {
- b, ok := f.Bar[name]
- if ok {
- b = f.Apply(b)
- } else {
- b = f.Q
- }
- return b
-}
-
-func foobarNew() {
- a := BazNew{}
- a.Q = 0 // should not be renamed, this is a limitation
-
- b := otherpkg.UnrelatedType{}
- b.Q = 0 // should not be renamed, this is a limitation
-}
diff --git a/tools/go_generics/generics_tests/consts/input.go b/tools/go_generics/generics_tests/consts/input.go
deleted file mode 100644
index 04b95fcc6..000000000
--- a/tools/go_generics/generics_tests/consts/input.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tests
-
-const c1 = 10
-const x, y, z = 100, 200, 300
-const v float32 = 1.0 + 2.0
-const s = "abc"
-const (
- A = 10
- B, C, D = 10, 20, 30
- S = "abc"
- T, U, V string = "abc", "def", "ghi"
-)
diff --git a/tools/go_generics/generics_tests/consts/opts.txt b/tools/go_generics/generics_tests/consts/opts.txt
deleted file mode 100644
index 4fb59dce8..000000000
--- a/tools/go_generics/generics_tests/consts/opts.txt
+++ /dev/null
@@ -1 +0,0 @@
--c=c1=20 -c=z=600 -c=v=3.3 -c=s="def" -c=A=20 -c=C=100 -c=S="def" -c=T="ABC"
diff --git a/tools/go_generics/generics_tests/consts/output/output.go b/tools/go_generics/generics_tests/consts/output/output.go
deleted file mode 100644
index 18d316cc9..000000000
--- a/tools/go_generics/generics_tests/consts/output/output.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-const c1 = 20
-const x, y, z = 100, 200, 600
-const v float32 = 3.3
-const s = "def"
-const (
- A = 20
- B, C, D = 10, 100, 30
- S = "def"
- T, U, V string = "ABC", "def", "ghi"
-)
diff --git a/tools/go_generics/generics_tests/imports/input.go b/tools/go_generics/generics_tests/imports/input.go
deleted file mode 100644
index 0f032c2a1..000000000
--- a/tools/go_generics/generics_tests/imports/input.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tests
-
-type T int
-
-var global T
-
-const (
- m = 0
- n = 0
-)
diff --git a/tools/go_generics/generics_tests/imports/opts.txt b/tools/go_generics/generics_tests/imports/opts.txt
deleted file mode 100644
index 87324be79..000000000
--- a/tools/go_generics/generics_tests/imports/opts.txt
+++ /dev/null
@@ -1 +0,0 @@
--t=T=sync.Mutex -c=n=math.Uint32 -c=m=math.Uint64 -import=sync=sync -import=math=mymathpath
diff --git a/tools/go_generics/generics_tests/imports/output/output.go b/tools/go_generics/generics_tests/imports/output/output.go
deleted file mode 100644
index 2488ca58c..000000000
--- a/tools/go_generics/generics_tests/imports/output/output.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- __generics_imported1 "mymathpath"
- __generics_imported0 "sync"
-)
-
-var global __generics_imported0.Mutex
-
-const (
- m = __generics_imported1.Uint64
- n = __generics_imported1.Uint32
-)
diff --git a/tools/go_generics/generics_tests/remove_typedef/input.go b/tools/go_generics/generics_tests/remove_typedef/input.go
deleted file mode 100644
index cf632bae7..000000000
--- a/tools/go_generics/generics_tests/remove_typedef/input.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tests
-
-func f(T) Q {
- return Q{}
-}
-
-type T struct{}
-
-type Q struct{}
-
-func (*T) f() {
-}
-
-func (T) g() {
-}
-
-func (*Q) f(T) T {
- return T{}
-}
-
-func (*Q) g(T) *T {
- return nil
-}
diff --git a/tools/go_generics/generics_tests/remove_typedef/opts.txt b/tools/go_generics/generics_tests/remove_typedef/opts.txt
deleted file mode 100644
index 9c8ecaada..000000000
--- a/tools/go_generics/generics_tests/remove_typedef/opts.txt
+++ /dev/null
@@ -1 +0,0 @@
--t=T=U
diff --git a/tools/go_generics/generics_tests/remove_typedef/output/output.go b/tools/go_generics/generics_tests/remove_typedef/output/output.go
deleted file mode 100644
index d44fd8e1c..000000000
--- a/tools/go_generics/generics_tests/remove_typedef/output/output.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-func f(U) Q {
- return Q{}
-}
-
-type Q struct{}
-
-func (*Q) f(U) U {
- return U{}
-}
-
-func (*Q) g(U) *U {
- return nil
-}
diff --git a/tools/go_generics/generics_tests/simple/input.go b/tools/go_generics/generics_tests/simple/input.go
deleted file mode 100644
index 2a917f16c..000000000
--- a/tools/go_generics/generics_tests/simple/input.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package tests
-
-type T int
-
-var global T
-
-func f(_ T, a int) {
-}
-
-func g(a T, b int) {
- var c T
- _ = c
-
- d := (*T)(nil)
- _ = d
-}
-
-type R struct {
- T
- a *T
-}
-
-var (
- Z *T = (*T)(nil)
-)
-
-const (
- X T = (T)(0)
-)
-
-type Y T
diff --git a/tools/go_generics/generics_tests/simple/opts.txt b/tools/go_generics/generics_tests/simple/opts.txt
deleted file mode 100644
index 7832ef66f..000000000
--- a/tools/go_generics/generics_tests/simple/opts.txt
+++ /dev/null
@@ -1 +0,0 @@
--t=T=Q -suffix=New
diff --git a/tools/go_generics/generics_tests/simple/output/output.go b/tools/go_generics/generics_tests/simple/output/output.go
deleted file mode 100644
index 6bfa0b25b..000000000
--- a/tools/go_generics/generics_tests/simple/output/output.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-var globalNew Q
-
-func fNew(_ Q, a int) {
-}
-
-func gNew(a Q, b int) {
- var c Q
- _ = c
-
- d := (*Q)(nil)
- _ = d
-}
-
-type RNew struct {
- Q
- a *Q
-}
-
-var (
- ZNew *Q = (*Q)(nil)
-)
-
-const (
- XNew Q = (Q)(0)
-)
-
-type YNew Q
diff --git a/tools/go_generics/globals/BUILD b/tools/go_generics/globals/BUILD
deleted file mode 100644
index 74853c7d2..000000000
--- a/tools/go_generics/globals/BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_library")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "globals",
- srcs = [
- "globals_visitor.go",
- "scope.go",
- ],
- importpath = "gvisor.dev/gvisor/tools/go_generics/globals",
- visibility = ["//tools/go_generics:__pkg__"],
-)
diff --git a/tools/go_generics/globals/globals_visitor.go b/tools/go_generics/globals/globals_visitor.go
deleted file mode 100644
index 883f21ebe..000000000
--- a/tools/go_generics/globals/globals_visitor.go
+++ /dev/null
@@ -1,597 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package globals provides an AST visitor that calls the visit function for all
-// global identifiers.
-package globals
-
-import (
- "fmt"
-
- "go/ast"
- "go/token"
- "path/filepath"
- "strconv"
-)
-
-// globalsVisitor holds the state used while traversing the nodes of a file in
-// search of globals.
-//
-// The visitor does two passes on the global declarations: the first one adds
-// all globals to the global scope (since Go allows references to globals that
-// haven't been declared yet), and the second one calls f() for the definition
-// and uses of globals found in the first pass.
-//
-// The implementation correctly handles cases when globals are aliased by
-// locals; in such cases, f() is not called.
-type globalsVisitor struct {
- // file is the file whose nodes are being visited.
- file *ast.File
-
- // fset is the file set the file being visited belongs to.
- fset *token.FileSet
-
- // f is the visit function to be called when a global symbol is reached.
- f func(*ast.Ident, SymKind)
-
- // scope is the current scope as nodes are visited.
- scope *scope
-
- // processAnon indicates whether we should process anonymous struct fields.
- // It does not perform strict checking on parameter types that share the same name
- // as the global type and therefore will rename them as well.
- processAnon bool
-}
-
-// unexpected is called when an unexpected node appears in the AST. It dumps
-// the location of the associated token and panics because this should only
-// happen when there is a bug in the traversal code.
-func (v *globalsVisitor) unexpected(p token.Pos) {
- panic(fmt.Sprintf("Unable to parse at %v", v.fset.Position(p)))
-}
-
-// pushScope creates a new scope and pushes it to the top of the scope stack.
-func (v *globalsVisitor) pushScope() {
- v.scope = newScope(v.scope)
-}
-
-// popScope removes the scope created by the last call to pushScope.
-func (v *globalsVisitor) popScope() {
- v.scope = v.scope.outer
-}
-
-// visitType is called when an expression is known to be a type, for example,
-// on the first argument of make(). It visits all children nodes and reports
-// any globals.
-func (v *globalsVisitor) visitType(ge ast.Expr) {
- switch e := ge.(type) {
- case *ast.Ident:
- if s := v.scope.deepLookup(e.Name); s != nil && s.scope.isGlobal() {
- v.f(e, s.kind)
- }
-
- case *ast.SelectorExpr:
- id := GetIdent(e.X)
- if id == nil {
- v.unexpected(e.X.Pos())
- }
-
- case *ast.StarExpr:
- v.visitType(e.X)
- case *ast.ParenExpr:
- v.visitType(e.X)
- case *ast.ChanType:
- v.visitType(e.Value)
- case *ast.Ellipsis:
- v.visitType(e.Elt)
- case *ast.ArrayType:
- v.visitExpr(e.Len)
- v.visitType(e.Elt)
- case *ast.MapType:
- v.visitType(e.Key)
- v.visitType(e.Value)
- case *ast.StructType:
- v.visitFields(e.Fields, KindUnknown)
- case *ast.FuncType:
- v.visitFields(e.Params, KindUnknown)
- v.visitFields(e.Results, KindUnknown)
- case *ast.InterfaceType:
- v.visitFields(e.Methods, KindUnknown)
- default:
- v.unexpected(ge.Pos())
- }
-}
-
-// visitFields visits all fields, and add symbols if kind isn't KindUnknown.
-func (v *globalsVisitor) visitFields(l *ast.FieldList, kind SymKind) {
- if l == nil {
- return
- }
-
- for _, f := range l.List {
- if kind != KindUnknown {
- for _, n := range f.Names {
- v.scope.add(n.Name, kind, n.Pos())
- }
- }
- v.visitType(f.Type)
- if f.Tag != nil {
- tag := ast.NewIdent(f.Tag.Value)
- v.f(tag, KindTag)
- // Replace the tag if updated.
- if tag.Name != f.Tag.Value {
- f.Tag.Value = tag.Name
- }
- }
- }
-}
-
-// visitGenDecl is called when a generic declaration is encountered, for example,
-// on variable, constant and type declarations. It adds all newly defined
-// symbols to the current scope and reports them if the current scope is the
-// global one.
-func (v *globalsVisitor) visitGenDecl(d *ast.GenDecl) {
- switch d.Tok {
- case token.IMPORT:
- case token.TYPE:
- for _, gs := range d.Specs {
- s := gs.(*ast.TypeSpec)
- v.scope.add(s.Name.Name, KindType, s.Name.Pos())
- if v.scope.isGlobal() {
- v.f(s.Name, KindType)
- }
- v.visitType(s.Type)
- }
- case token.CONST, token.VAR:
- kind := KindConst
- if d.Tok == token.VAR {
- kind = KindVar
- }
-
- for _, gs := range d.Specs {
- s := gs.(*ast.ValueSpec)
- if s.Type != nil {
- v.visitType(s.Type)
- }
-
- for _, e := range s.Values {
- v.visitExpr(e)
- }
-
- for _, n := range s.Names {
- if v.scope.isGlobal() {
- v.f(n, kind)
- }
- v.scope.add(n.Name, kind, n.Pos())
- }
- }
- default:
- v.unexpected(d.Pos())
- }
-}
-
-// isViableType determines if the given expression is a viable type expression,
-// that is, if it could be interpreted as a type, for example, sync.Mutex,
-// myType, func(int)int, as opposed to -1, 2 * 2, a + b, etc.
-func (v *globalsVisitor) isViableType(expr ast.Expr) bool {
- switch e := expr.(type) {
- case *ast.Ident:
- // This covers the plain identifier case. When we see it, we
- // have to check if it resolves to a type; if the symbol is not
- // known, we'll claim it's viable as a type.
- s := v.scope.deepLookup(e.Name)
- return s == nil || s.kind == KindType
-
- case *ast.ChanType, *ast.ArrayType, *ast.MapType, *ast.StructType, *ast.FuncType, *ast.InterfaceType, *ast.Ellipsis:
- // This covers the following cases:
- // 1. ChanType:
- // chan T
- // <-chan T
- // chan<- T
- // 2. ArrayType:
- // [Expr]T
- // 3. MapType:
- // map[T]U
- // 4. StructType:
- // struct { Fields }
- // 5. FuncType:
- // func(Fields)Returns
- // 6. Interface:
- // interface { Fields }
- // 7. Ellipsis:
- // ...T
- return true
-
- case *ast.SelectorExpr:
- // The only case in which an expression involving a selector can
- // be a type is if it has the following form X.T, where X is an
- // import, and T is a type exported by X.
- //
- // There's no way to know whether T is a type because we don't
- // parse imports. So we just claim that this is a viable type;
- // it doesn't affect the general result because we don't visit
- // imported symbols.
- id := GetIdent(e.X)
- if id == nil {
- return false
- }
-
- s := v.scope.deepLookup(id.Name)
- return s != nil && s.kind == KindImport
-
- case *ast.StarExpr:
- // This covers the *T case. The expression is a viable type if
- // T is.
- return v.isViableType(e.X)
-
- case *ast.ParenExpr:
- // This covers the (T) case. The expression is a viable type if
- // T is.
- return v.isViableType(e.X)
-
- default:
- return false
- }
-}
-
-// visitCallExpr visits a "call expression" which can be either a
-// function/method call (e.g., f(), pkg.f(), obj.f(), etc.) call or a type
-// conversion (e.g., int32(1), (*sync.Mutex)(ptr), etc.).
-func (v *globalsVisitor) visitCallExpr(e *ast.CallExpr) {
- if v.isViableType(e.Fun) {
- v.visitType(e.Fun)
- } else {
- v.visitExpr(e.Fun)
- }
-
- // If the function being called is new or make, the first argument is
- // a type, so it needs to be visited as such.
- first := 0
- if id := GetIdent(e.Fun); id != nil && (id.Name == "make" || id.Name == "new") {
- if len(e.Args) > 0 {
- v.visitType(e.Args[0])
- }
- first = 1
- }
-
- for i := first; i < len(e.Args); i++ {
- v.visitExpr(e.Args[i])
- }
-}
-
-// visitExpr visits all nodes of an expression, and reports any globals that it
-// finds.
-func (v *globalsVisitor) visitExpr(ge ast.Expr) {
- switch e := ge.(type) {
- case nil:
- case *ast.Ident:
- if s := v.scope.deepLookup(e.Name); s != nil && s.scope.isGlobal() {
- v.f(e, s.kind)
- }
-
- case *ast.BasicLit:
- case *ast.CompositeLit:
- v.visitType(e.Type)
- for _, ne := range e.Elts {
- v.visitExpr(ne)
- }
- case *ast.FuncLit:
- v.pushScope()
- v.visitFields(e.Type.Params, KindParameter)
- v.visitFields(e.Type.Results, KindResult)
- v.visitBlockStmt(e.Body)
- v.popScope()
-
- case *ast.BinaryExpr:
- v.visitExpr(e.X)
- v.visitExpr(e.Y)
-
- case *ast.CallExpr:
- v.visitCallExpr(e)
-
- case *ast.IndexExpr:
- v.visitExpr(e.X)
- v.visitExpr(e.Index)
-
- case *ast.KeyValueExpr:
- v.visitExpr(e.Value)
-
- case *ast.ParenExpr:
- v.visitExpr(e.X)
-
- case *ast.SelectorExpr:
- v.visitExpr(e.X)
- if v.processAnon {
- v.visitExpr(e.Sel)
- }
-
- case *ast.SliceExpr:
- v.visitExpr(e.X)
- v.visitExpr(e.Low)
- v.visitExpr(e.High)
- v.visitExpr(e.Max)
-
- case *ast.StarExpr:
- v.visitExpr(e.X)
-
- case *ast.TypeAssertExpr:
- v.visitExpr(e.X)
- if e.Type != nil {
- v.visitType(e.Type)
- }
-
- case *ast.UnaryExpr:
- v.visitExpr(e.X)
-
- default:
- v.unexpected(ge.Pos())
- }
-}
-
-// GetIdent returns the identifier associated with the given expression by
-// removing parentheses if needed.
-func GetIdent(expr ast.Expr) *ast.Ident {
- switch e := expr.(type) {
- case *ast.Ident:
- return e
- case *ast.ParenExpr:
- return GetIdent(e.X)
- default:
- return nil
- }
-}
-
-// visitStmt visits all nodes of a statement, and reports any globals that it
-// finds. It also adds to the current scope new symbols defined/declared.
-func (v *globalsVisitor) visitStmt(gs ast.Stmt) {
- switch s := gs.(type) {
- case nil, *ast.BranchStmt, *ast.EmptyStmt:
- case *ast.AssignStmt:
- for _, e := range s.Rhs {
- v.visitExpr(e)
- }
-
- // We visit the LHS after the RHS because the symbols we'll
- // potentially add to the table aren't meant to be visible to
- // the RHS.
- for _, e := range s.Lhs {
- if s.Tok == token.DEFINE {
- if n := GetIdent(e); n != nil {
- v.scope.add(n.Name, KindVar, n.Pos())
- }
- }
- v.visitExpr(e)
- }
-
- case *ast.BlockStmt:
- v.visitBlockStmt(s)
-
- case *ast.DeclStmt:
- v.visitGenDecl(s.Decl.(*ast.GenDecl))
-
- case *ast.DeferStmt:
- v.visitCallExpr(s.Call)
-
- case *ast.ExprStmt:
- v.visitExpr(s.X)
-
- case *ast.ForStmt:
- v.pushScope()
- v.visitStmt(s.Init)
- v.visitExpr(s.Cond)
- v.visitStmt(s.Post)
- v.visitBlockStmt(s.Body)
- v.popScope()
-
- case *ast.GoStmt:
- v.visitCallExpr(s.Call)
-
- case *ast.IfStmt:
- v.pushScope()
- v.visitStmt(s.Init)
- v.visitExpr(s.Cond)
- v.visitBlockStmt(s.Body)
- v.visitStmt(s.Else)
- v.popScope()
-
- case *ast.IncDecStmt:
- v.visitExpr(s.X)
-
- case *ast.LabeledStmt:
- v.visitStmt(s.Stmt)
-
- case *ast.RangeStmt:
- v.pushScope()
- v.visitExpr(s.X)
- if s.Tok == token.DEFINE {
- if n := GetIdent(s.Key); n != nil {
- v.scope.add(n.Name, KindVar, n.Pos())
- }
-
- if n := GetIdent(s.Value); n != nil {
- v.scope.add(n.Name, KindVar, n.Pos())
- }
- }
- v.visitExpr(s.Key)
- v.visitExpr(s.Value)
- v.visitBlockStmt(s.Body)
- v.popScope()
-
- case *ast.ReturnStmt:
- for _, r := range s.Results {
- v.visitExpr(r)
- }
-
- case *ast.SelectStmt:
- for _, ns := range s.Body.List {
- c := ns.(*ast.CommClause)
-
- v.pushScope()
- v.visitStmt(c.Comm)
- for _, bs := range c.Body {
- v.visitStmt(bs)
- }
- v.popScope()
- }
-
- case *ast.SendStmt:
- v.visitExpr(s.Chan)
- v.visitExpr(s.Value)
-
- case *ast.SwitchStmt:
- v.pushScope()
- v.visitStmt(s.Init)
- v.visitExpr(s.Tag)
- for _, ns := range s.Body.List {
- c := ns.(*ast.CaseClause)
- v.pushScope()
- for _, ce := range c.List {
- v.visitExpr(ce)
- }
- for _, bs := range c.Body {
- v.visitStmt(bs)
- }
- v.popScope()
- }
- v.popScope()
-
- case *ast.TypeSwitchStmt:
- v.pushScope()
- v.visitStmt(s.Init)
- v.visitStmt(s.Assign)
- for _, ns := range s.Body.List {
- c := ns.(*ast.CaseClause)
- v.pushScope()
- for _, ce := range c.List {
- v.visitType(ce)
- }
- for _, bs := range c.Body {
- v.visitStmt(bs)
- }
- v.popScope()
- }
- v.popScope()
-
- default:
- v.unexpected(gs.Pos())
- }
-}
-
-// visitBlockStmt visits all statements in the block, adding symbols to a newly
-// created scope.
-func (v *globalsVisitor) visitBlockStmt(s *ast.BlockStmt) {
- v.pushScope()
- for _, c := range s.List {
- v.visitStmt(c)
- }
- v.popScope()
-}
-
-// visitFuncDecl is called when a function or method declaration is encountered.
-// it creates a new scope for the function [optional] receiver, parameters and
-// results, and visits all children nodes.
-func (v *globalsVisitor) visitFuncDecl(d *ast.FuncDecl) {
- // We don't report methods.
- if d.Recv == nil {
- v.f(d.Name, KindFunction)
- }
-
- v.pushScope()
- v.visitFields(d.Recv, KindReceiver)
- v.visitFields(d.Type.Params, KindParameter)
- v.visitFields(d.Type.Results, KindResult)
- if d.Body != nil {
- v.visitBlockStmt(d.Body)
- }
- v.popScope()
-}
-
-// globalsFromDecl is called in the first, and adds symbols to global scope.
-func (v *globalsVisitor) globalsFromGenDecl(d *ast.GenDecl) {
- switch d.Tok {
- case token.IMPORT:
- for _, gs := range d.Specs {
- s := gs.(*ast.ImportSpec)
- if s.Name == nil {
- str, _ := strconv.Unquote(s.Path.Value)
- v.scope.add(filepath.Base(str), KindImport, s.Path.Pos())
- } else if s.Name.Name != "_" {
- v.scope.add(s.Name.Name, KindImport, s.Name.Pos())
- }
- }
- case token.TYPE:
- for _, gs := range d.Specs {
- s := gs.(*ast.TypeSpec)
- v.scope.add(s.Name.Name, KindType, s.Name.Pos())
- }
- case token.CONST, token.VAR:
- kind := KindConst
- if d.Tok == token.VAR {
- kind = KindVar
- }
-
- for _, s := range d.Specs {
- for _, n := range s.(*ast.ValueSpec).Names {
- v.scope.add(n.Name, kind, n.Pos())
- }
- }
- default:
- v.unexpected(d.Pos())
- }
-}
-
-// visit implements the visiting of globals. It does performs the two passes
-// described in the description of the globalsVisitor struct.
-func (v *globalsVisitor) visit() {
- // Gather all symbols in the global scope. This excludes methods.
- v.pushScope()
- for _, gd := range v.file.Decls {
- switch d := gd.(type) {
- case *ast.GenDecl:
- v.globalsFromGenDecl(d)
- case *ast.FuncDecl:
- if d.Recv == nil {
- v.scope.add(d.Name.Name, KindFunction, d.Name.Pos())
- }
- default:
- v.unexpected(gd.Pos())
- }
- }
-
- // Go through the contents of the declarations.
- for _, gd := range v.file.Decls {
- switch d := gd.(type) {
- case *ast.GenDecl:
- v.visitGenDecl(d)
- case *ast.FuncDecl:
- v.visitFuncDecl(d)
- }
- }
-}
-
-// Visit traverses the provided AST and calls f() for each identifier that
-// refers to global names. The global name must be defined in the file itself.
-//
-// The function f() is allowed to modify the identifier, for example, to rename
-// uses of global references.
-func Visit(fset *token.FileSet, file *ast.File, f func(*ast.Ident, SymKind), processAnon bool) {
- v := globalsVisitor{
- fset: fset,
- file: file,
- f: f,
- processAnon: processAnon,
- }
-
- v.visit()
-}
diff --git a/tools/go_generics/globals/scope.go b/tools/go_generics/globals/scope.go
deleted file mode 100644
index 96c965ea2..000000000
--- a/tools/go_generics/globals/scope.go
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package globals
-
-import (
- "go/token"
-)
-
-// SymKind specifies the kind of a global symbol. For example, a variable, const
-// function, etc.
-type SymKind int
-
-// Constants for different kinds of symbols.
-const (
- KindUnknown SymKind = iota
- KindImport
- KindType
- KindVar
- KindConst
- KindFunction
- KindReceiver
- KindParameter
- KindResult
- KindTag
-)
-
-type symbol struct {
- kind SymKind
- pos token.Pos
- scope *scope
-}
-
-type scope struct {
- outer *scope
- syms map[string]*symbol
-}
-
-func newScope(outer *scope) *scope {
- return &scope{
- outer: outer,
- syms: make(map[string]*symbol),
- }
-}
-
-func (s *scope) isGlobal() bool {
- return s.outer == nil
-}
-
-func (s *scope) lookup(n string) *symbol {
- return s.syms[n]
-}
-
-func (s *scope) deepLookup(n string) *symbol {
- for x := s; x != nil; x = x.outer {
- if sym := x.lookup(n); sym != nil {
- return sym
- }
- }
- return nil
-}
-
-func (s *scope) add(name string, kind SymKind, pos token.Pos) {
- s.syms[name] = &symbol{
- kind: kind,
- pos: pos,
- scope: s,
- }
-}
diff --git a/tools/go_generics/go_generics_unittest.sh b/tools/go_generics/go_generics_unittest.sh
deleted file mode 100755
index 44b22db91..000000000
--- a/tools/go_generics/go_generics_unittest.sh
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/bash
-
-# Copyright 2018 The gVisor Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Bash "safe-mode": Treat command failures as fatal (even those that occur in
-# pipes), and treat unset variables as errors.
-set -eu -o pipefail
-
-# This file will be generated as a self-extracting shell script in order to
-# eliminate the need for any runtime dependencies. The tarball at the end will
-# include the go_generics binary, as well as a subdirectory named
-# generics_tests. See the BUILD file for more information.
-declare -r temp=$(mktemp -d)
-function cleanup() {
- rm -rf "${temp}"
-}
-# trap cleanup EXIT
-
-# Print message in "$1" then exit with status 1.
-function die () {
- echo "$1" 1>&2
- exit 1
-}
-
-# This prints the line number of __BUNDLE__ below, that should be the last line
-# of this script. After that point, the concatenated archive will be the
-# contents.
-declare -r tgz=`awk '/^__BUNDLE__/ {print NR + 1; exit 0; }' $0`
-tail -n+"${tgz}" $0 | tar -xzv -C "${temp}"
-
-# The target for the test.
-declare -r binary="$(find ${temp} -type f -a -name go_generics)"
-declare -r input_dirs="$(find ${temp} -type d -a -name generics_tests)/*"
-
-# Go through all test cases.
-for f in ${input_dirs}; do
- base=$(basename "${f}")
-
- # Run go_generics on the input file.
- opts=$(head -n 1 ${f}/opts.txt)
- out="${f}/output/generated.go"
- expected="${f}/output/output.go"
- ${binary} ${opts} "-i=${f}/input.go" "-o=${out}" || die "go_generics failed for test case \"${base}\""
-
- # Compare the outputs.
- diff ${expected} ${out}
- if [ $? -ne 0 ]; then
- echo "Expected:"
- cat ${expected}
- echo "Actual:"
- cat ${out}
- die "Actual output is different from expected for test \"${base}\""
- fi
-done
-
-echo "PASS"
-exit 0
-__BUNDLE__
diff --git a/tools/go_generics/go_merge/BUILD b/tools/go_generics/go_merge/BUILD
deleted file mode 100644
index 02b09120e..000000000
--- a/tools/go_generics/go_merge/BUILD
+++ /dev/null
@@ -1,9 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary")
-
-package(licenses = ["notice"])
-
-go_binary(
- name = "go_merge",
- srcs = ["main.go"],
- visibility = ["//visibility:public"],
-)
diff --git a/tools/go_generics/go_merge/main.go b/tools/go_generics/go_merge/main.go
deleted file mode 100644
index f6a331123..000000000
--- a/tools/go_generics/go_merge/main.go
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "bytes"
- "flag"
- "fmt"
- "go/ast"
- "go/format"
- "go/parser"
- "go/token"
- "io/ioutil"
- "os"
- "path/filepath"
- "strconv"
-)
-
-var (
- output = flag.String("o", "", "output `file`")
-)
-
-func fatalf(s string, args ...interface{}) {
- fmt.Fprintf(os.Stderr, s, args...)
- os.Exit(1)
-}
-
-func main() {
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, "Usage: %s [options] <input1> [<input2> ...]\n", os.Args[0])
- flag.PrintDefaults()
- }
-
- flag.Parse()
- if *output == "" || len(flag.Args()) == 0 {
- flag.Usage()
- os.Exit(1)
- }
-
- // Load all files.
- files := make(map[string]*ast.File)
- fset := token.NewFileSet()
- var name string
- for _, fname := range flag.Args() {
- f, err := parser.ParseFile(fset, fname, nil, parser.ParseComments|parser.DeclarationErrors|parser.SpuriousErrors)
- if err != nil {
- fatalf("%v\n", err)
- }
-
- files[fname] = f
- if name == "" {
- name = f.Name.Name
- } else if name != f.Name.Name {
- fatalf("Expected '%s' for package name instead of '%s'.\n", name, f.Name.Name)
- }
- }
-
- // Merge all files into one.
- pkg := &ast.Package{
- Name: name,
- Files: files,
- }
- f := ast.MergePackageFiles(pkg, ast.FilterUnassociatedComments|ast.FilterFuncDuplicates|ast.FilterImportDuplicates)
-
- // Create a new declaration slice with all imports at the top, merging any
- // redundant imports.
- imports := make(map[string]*ast.ImportSpec)
- var anonImports []*ast.ImportSpec
- for _, d := range f.Decls {
- if g, ok := d.(*ast.GenDecl); ok && g.Tok == token.IMPORT {
- for _, s := range g.Specs {
- i := s.(*ast.ImportSpec)
- p, _ := strconv.Unquote(i.Path.Value)
- var n string
- if i.Name == nil {
- n = filepath.Base(p)
- } else {
- n = i.Name.Name
- }
- if n == "_" {
- anonImports = append(anonImports, i)
- } else {
- if i2, ok := imports[n]; ok {
- if first, second := i.Path.Value, i2.Path.Value; first != second {
- fatalf("Conflicting paths for import name '%s': '%s' vs. '%s'\n", n, first, second)
- }
- } else {
- imports[n] = i
- }
- }
- }
- }
- }
- newDecls := make([]ast.Decl, 0, len(f.Decls))
- if l := len(imports) + len(anonImports); l > 0 {
- // Non-NoPos Lparen is needed for Go to recognize more than one spec in
- // ast.GenDecl.Specs.
- d := &ast.GenDecl{
- Tok: token.IMPORT,
- Lparen: token.NoPos + 1,
- Specs: make([]ast.Spec, 0, l),
- }
- for _, i := range imports {
- d.Specs = append(d.Specs, i)
- }
- for _, i := range anonImports {
- d.Specs = append(d.Specs, i)
- }
- newDecls = append(newDecls, d)
- }
- for _, d := range f.Decls {
- if g, ok := d.(*ast.GenDecl); !ok || g.Tok != token.IMPORT {
- newDecls = append(newDecls, d)
- }
- }
- f.Decls = newDecls
-
- // Write the output file.
- var buf bytes.Buffer
- if err := format.Node(&buf, fset, f); err != nil {
- fatalf("%v\n", err)
- }
-
- if err := ioutil.WriteFile(*output, buf.Bytes(), 0644); err != nil {
- fatalf("%v\n", err)
- }
-}
diff --git a/tools/go_generics/imports.go b/tools/go_generics/imports.go
deleted file mode 100644
index 148dc7216..000000000
--- a/tools/go_generics/imports.go
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "bytes"
- "fmt"
- "go/ast"
- "go/format"
- "go/parser"
- "go/token"
- "strconv"
-
- "gvisor.dev/gvisor/tools/go_generics/globals"
-)
-
-type importedPackage struct {
- newName string
- path string
-}
-
-// updateImportIdent modifies the given import identifier with the new name
-// stored in the used map. If the identifier doesn't exist in the used map yet,
-// a new name is generated and inserted into the map.
-func updateImportIdent(orig string, imports mapValue, id *ast.Ident, used map[string]*importedPackage) error {
- importName := id.Name
-
- // If the name is already in the table, just use the new name.
- m := used[importName]
- if m != nil {
- id.Name = m.newName
- return nil
- }
-
- // Create a new entry in the used map.
- path := imports[importName]
- if path == "" {
- return fmt.Errorf("Unknown path to package '%s', used in '%s'", importName, orig)
- }
-
- m = &importedPackage{
- newName: fmt.Sprintf("__generics_imported%d", len(used)),
- path: strconv.Quote(path),
- }
- used[importName] = m
-
- id.Name = m.newName
-
- return nil
-}
-
-// convertExpression creates a new string that is a copy of the input one with
-// all imports references renamed to the names in the "used" map. If the
-// referenced import isn't in "used" yet, a new one is created based on the path
-// in "imports" and stored in "used". For example, if string s is
-// "math.MaxUint32-math.MaxUint16+10", it would be converted to
-// "x.MaxUint32-x.MathUint16+10", where x is a generated name.
-func convertExpression(s string, imports mapValue, used map[string]*importedPackage) (string, error) {
- // Parse the expression in the input string.
- expr, err := parser.ParseExpr(s)
- if err != nil {
- return "", fmt.Errorf("Unable to parse \"%s\": %v", s, err)
- }
-
- // Go through the AST and update references.
- var retErr error
- ast.Inspect(expr, func(n ast.Node) bool {
- switch x := n.(type) {
- case *ast.SelectorExpr:
- if id := globals.GetIdent(x.X); id != nil {
- if err := updateImportIdent(s, imports, id, used); err != nil {
- retErr = err
- }
- return false
- }
- }
- return true
- })
- if retErr != nil {
- return "", retErr
- }
-
- // Convert the modified AST back to a string.
- fset := token.NewFileSet()
- var buf bytes.Buffer
- if err := format.Node(&buf, fset, expr); err != nil {
- return "", err
- }
-
- return string(buf.Bytes()), nil
-}
-
-// updateImports replaces all maps in the input slice with copies where the
-// mapped values have had all references to imported packages renamed to
-// generated names. It also returns an import declaration for all the renamed
-// import packages.
-//
-// For example, if the input maps contains A=math.B and C=math.D, the updated
-// maps will instead contain A=__generics_imported0.B and
-// C=__generics_imported0.C, and the 'import __generics_imported0 "math"' would
-// be returned as the import declaration.
-func updateImports(maps []mapValue, imports mapValue) (ast.Decl, error) {
- importsUsed := make(map[string]*importedPackage)
-
- // Update all maps.
- for i, m := range maps {
- newMap := make(mapValue)
- for n, e := range m {
- updated, err := convertExpression(e, imports, importsUsed)
- if err != nil {
- return nil, err
- }
-
- newMap[n] = updated
- }
- maps[i] = newMap
- }
-
- // Nothing else to do if no imports are used in the expressions.
- if len(importsUsed) == 0 {
- return nil, nil
- }
-
- // Create spec array for each new import.
- specs := make([]ast.Spec, 0, len(importsUsed))
- for _, i := range importsUsed {
- specs = append(specs, &ast.ImportSpec{
- Name: &ast.Ident{Name: i.newName},
- Path: &ast.BasicLit{Value: i.path},
- })
- }
-
- return &ast.GenDecl{
- Tok: token.IMPORT,
- Specs: specs,
- Lparen: token.NoPos + 1,
- }, nil
-}
diff --git a/tools/go_generics/remove.go b/tools/go_generics/remove.go
deleted file mode 100644
index 568a6bbd3..000000000
--- a/tools/go_generics/remove.go
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "go/ast"
- "go/token"
-)
-
-type typeSet map[string]struct{}
-
-// isTypeOrPointerToType determines if the given AST expression represents a
-// type or a pointer to a type that exists in the provided type set.
-func isTypeOrPointerToType(set typeSet, expr ast.Expr, starCount int) bool {
- switch e := expr.(type) {
- case *ast.Ident:
- _, ok := set[e.Name]
- return ok
- case *ast.StarExpr:
- if starCount > 1 {
- return false
- }
- return isTypeOrPointerToType(set, e.X, starCount+1)
- case *ast.ParenExpr:
- return isTypeOrPointerToType(set, e.X, starCount)
- default:
- return false
- }
-}
-
-// isMethodOf determines if the given function declaration is a method of one
-// of the types in the provided type set. To do that, it checks if the function
-// has a receiver and that its type is either T or *T, where T is a type that
-// exists in the set. This is per the spec:
-//
-// That parameter section must declare a single parameter, the receiver. Its
-// type must be of the form T or *T (possibly using parentheses) where T is a
-// type name. The type denoted by T is called the receiver base type; it must
-// not be a pointer or interface type and it must be declared in the same
-// package as the method.
-func isMethodOf(set typeSet, f *ast.FuncDecl) bool {
- // If the function doesn't have exactly one receiver, then it's
- // definitely not a method.
- if f.Recv == nil || len(f.Recv.List) != 1 {
- return false
- }
-
- return isTypeOrPointerToType(set, f.Recv.List[0].Type, 0)
-}
-
-// removeTypeDefinitions removes the definition of all types contained in the
-// provided type set.
-func removeTypeDefinitions(set typeSet, d *ast.GenDecl) {
- if d.Tok != token.TYPE {
- return
- }
-
- i := 0
- for _, gs := range d.Specs {
- s := gs.(*ast.TypeSpec)
- if _, ok := set[s.Name.Name]; !ok {
- d.Specs[i] = gs
- i++
- }
- }
-
- d.Specs = d.Specs[:i]
-}
-
-// removeTypes removes from the AST the definition of all types and their
-// method sets that are contained in the provided type set.
-func removeTypes(set typeSet, f *ast.File) {
- // Go through the top-level declarations.
- i := 0
- for _, decl := range f.Decls {
- keep := true
- switch d := decl.(type) {
- case *ast.GenDecl:
- countBefore := len(d.Specs)
- removeTypeDefinitions(set, d)
- keep = countBefore == 0 || len(d.Specs) > 0
- case *ast.FuncDecl:
- keep = !isMethodOf(set, d)
- }
-
- if keep {
- f.Decls[i] = decl
- i++
- }
- }
-
- f.Decls = f.Decls[:i]
-}
diff --git a/tools/go_generics/rules_tests/BUILD b/tools/go_generics/rules_tests/BUILD
deleted file mode 100644
index 9d26a88b7..000000000
--- a/tools/go_generics/rules_tests/BUILD
+++ /dev/null
@@ -1,43 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_test")
-load("//tools/go_generics:defs.bzl", "go_template", "go_template_instance")
-
-package(licenses = ["notice"])
-
-go_template_instance(
- name = "instance",
- out = "instance_test.go",
- consts = {
- "n": "20",
- "m": "\"test\"",
- "o": "math.MaxUint64",
- },
- imports = {
- "math": "math",
- },
- package = "template_test",
- template = ":test_template",
- types = {
- "t": "int",
- },
-)
-
-go_template(
- name = "test_template",
- srcs = [
- "template.go",
- ],
- opt_consts = [
- "n",
- "m",
- "o",
- ],
- opt_types = ["t"],
-)
-
-go_test(
- name = "template_test",
- srcs = [
- "instance_test.go",
- "template_test.go",
- ],
-)
diff --git a/tools/go_generics/rules_tests/template.go b/tools/go_generics/rules_tests/template.go
deleted file mode 100644
index aace61da1..000000000
--- a/tools/go_generics/rules_tests/template.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package template
-
-type t float
-
-const (
- n t = 10.1
- m = "abc"
- o = 0
-)
-
-func max(a, b t) t {
- if a > b {
- return a
- }
- return b
-}
-
-func add(a t) t {
- return a + n
-}
-
-func getName() string {
- return m
-}
-
-func getMax() uint64 {
- return o
-}
diff --git a/tools/go_generics/rules_tests/template_test.go b/tools/go_generics/rules_tests/template_test.go
deleted file mode 100644
index b2a3446ef..000000000
--- a/tools/go_generics/rules_tests/template_test.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package template_test
-
-import (
- "math"
- "testing"
-)
-
-func TestMax(t *testing.T) {
- var a int = max(10, 20)
- if a != 20 {
- t.Errorf("Bad result of max, got %v, want %v", a, 20)
- }
-}
-
-func TestIntConst(t *testing.T) {
- var a int = add(10)
- if a != 30 {
- t.Errorf("Bad result of add, got %v, want %v", a, 30)
- }
-}
-
-func TestStrConst(t *testing.T) {
- v := getName()
- if v != "test" {
- t.Errorf("Bad name, got %v, want %v", v, "test")
- }
-}
-
-func TestImport(t *testing.T) {
- v := getMax()
- if v != math.MaxUint64 {
- t.Errorf("Bad max value, got %v, want %v", v, uint64(math.MaxUint64))
- }
-}
diff --git a/tools/go_marshal/BUILD b/tools/go_marshal/BUILD
deleted file mode 100644
index c862b277c..000000000
--- a/tools/go_marshal/BUILD
+++ /dev/null
@@ -1,14 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary")
-
-package(licenses = ["notice"])
-
-go_binary(
- name = "go_marshal",
- srcs = ["main.go"],
- visibility = [
- "//:sandbox",
- ],
- deps = [
- "//tools/go_marshal/gomarshal",
- ],
-)
diff --git a/tools/go_marshal/README.md b/tools/go_marshal/README.md
deleted file mode 100644
index 481575bd3..000000000
--- a/tools/go_marshal/README.md
+++ /dev/null
@@ -1,164 +0,0 @@
-This package implements the go_marshal utility.
-
-# Overview
-
-`go_marshal` is a code generation utility similar to `go_stateify` for
-automatically generating code to marshal go data structures to memory.
-
-`go_marshal` attempts to improve on `binary.Write` and the sentry's
-`binary.Marshal` by moving the go runtime reflection necessary to marshal a
-struct to compile-time.
-
-`go_marshal` automatically generates implementations for `abi.Marshallable` and
-`safemem.{Reader,Writer}`. Call-sites for serialization (typically syscall
-implementations) can directly invoke `safemem.Reader.ReadToBlocks` and
-`safemem.Writer.WriteFromBlocks`. Data structures that require custom
-serialization will have manual implementations for these interfaces.
-
-Data structures can be flagged for code generation by adding a struct-level
-comment `// +marshal`.
-
-# Usage
-
-See `defs.bzl`: two new rules are provided, `go_marshal` and `go_library`.
-
-The recommended way to generate a go library with marshalling is to use the
-`go_library` with mostly identical configuration as the native go_library rule.
-
-```
-load("<PKGPATH>/gvisor/tools/go_marshal:defs.bzl", "go_library")
-
-go_library(
- name = "foo",
- srcs = ["foo.go"],
-)
-```
-
-Under the hood, the `go_marshal` rule is used to generate a file that will
-appear in a Go target; the output file should appear explicitly in a srcs list.
-For example (note that the above is the preferred method):
-
-```
-load("<PKGPATH>/gvisor/tools/go_marshal:defs.bzl", "go_marshal")
-
-go_marshal(
- name = "foo_abi",
- srcs = ["foo.go"],
- out = "foo_abi.go",
- package = "foo",
-)
-
-go_library(
- name = "foo",
- srcs = [
- "foo.go",
- "foo_abi.go",
- ],
- deps = [
- "<PKGPATH>/gvisor/pkg/abi",
- "<PKGPATH>/gvisor/pkg/sentry/safemem/safemem",
- "<PKGPATH>/gvisor/pkg/sentry/usermem/usermem",
- ],
-)
-```
-
-As part of the interface generation, `go_marshal` also generates some tests for
-sanity checking the struct definitions for potential alignment issues, and a
-simple round-trip test through Marshal/Unmarshal to verify the implementation.
-These tests use reflection to verify properties of the ABI struct, and should be
-considered part of the generated interfaces (but are too expensive to execute at
-runtime). Ensure these tests run at some point.
-
-```
-$ cat BUILD
-load("<PKGPATH>/gvisor/tools/go_marshal:defs.bzl", "go_library")
-
-go_library(
- name = "foo",
- srcs = ["foo.go"],
-)
-$ blaze build :foo
-$ blaze query ...
-<path-to-dir>:foo_abi_autogen
-<path-to-dir>:foo_abi_autogen_test
-$ blaze test :foo_abi_autogen_test
-<test-output>
-```
-
-# Restrictions
-
-Not all valid go type definitions can be used with `go_marshal`. `go_marshal` is
-intended for ABI structs, which have these additional restrictions:
-
-- At the moment, `go_marshal` only supports struct declarations.
-
-- Structs are marshalled as packed types. This means no implicit padding is
- inserted between fields shorter than the platform register size. For
- alignment, manually insert padding fields.
-
-- Structs used with `go_marshal` must have a compile-time static size. This
- means no dynamically sizes fields like slices or strings. Use statically
- sized array (byte arrays for strings) instead.
-
-- No pointers, channel, map or function pointer fields, and no fields that are
- arrays of these types. These don't make sense in an ABI data structure.
-
-- We could support opaque pointers as `uintptr`, but this is currently not
- implemented. Implementing this would require handling the architecture
- dependent native pointer size.
-
-- Fields must either be a primitive integer type (`byte`,
- `[u]int{8,16,32,64}`), or of a type that implements abi.Marshallable.
-
-- `int` and `uint` fields are not allowed. Use an explicitly-sized numeric
- type.
-
-- `float*` fields are currently not supported, but could be if necessary.
-
-# Appendix
-
-## Working with Non-Packed Structs
-
-ABI structs must generally be packed types, meaning they should have no implicit
-padding between short fields. However, if a field is tagged
-`marshal:"unaligned"`, `go_marshal` will fall back to a safer but slower
-mechanism to deal with potentially unaligned fields.
-
-Note that the non-packed property is inheritted by any other struct that embeds
-this struct, since the `go_marshal` tool currently can't reason about alignments
-for embedded structs that are not aligned.
-
-Because of this, it's generally best to avoid using `marshal:"unaligned"` and
-insert explicit padding fields instead.
-
-## Debugging go_marshal
-
-To enable debugging output from the go marshal tool, pass the `-debug` flag to
-the tool. When using the build rules from above, add a `debug = True` field to
-the build rule like this:
-
-```
-load("<PKGPATH>/gvisor/tools/go_marshal:defs.bzl", "go_library")
-
-go_library(
- name = "foo",
- srcs = ["foo.go"],
- debug = True,
-)
-```
-
-## Modifying the `go_marshal` Tool
-
-The following are some guidelines for modifying the `go_marshal` tool:
-
-- The `go_marshal` tool currently does a single pass over all types requesting
- code generation, in arbitrary order. This means the generated code can't
- directly obtain information about embedded marshallable types at
- compile-time. One way to work around this restriction is to add a new
- Marshallable interface method providing this piece of information, and
- calling it from the generated code. Use this sparingly, as we want to rely
- on compile-time information as much as possible for performance.
-
-- No runtime reflection in the code generated for the marshallable interface.
- The entire point of the tool is to avoid runtime reflection. The generated
- tests may use reflection.
diff --git a/tools/go_marshal/analysis/BUILD b/tools/go_marshal/analysis/BUILD
deleted file mode 100644
index c859ced77..000000000
--- a/tools/go_marshal/analysis/BUILD
+++ /dev/null
@@ -1,13 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_library")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "analysis",
- testonly = 1,
- srcs = ["analysis_unsafe.go"],
- importpath = "gvisor.dev/gvisor/tools/go_marshal/analysis",
- visibility = [
- "//:sandbox",
- ],
-)
diff --git a/tools/go_marshal/analysis/analysis_unsafe.go b/tools/go_marshal/analysis/analysis_unsafe.go
deleted file mode 100644
index 9a9a4f298..000000000
--- a/tools/go_marshal/analysis/analysis_unsafe.go
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package analysis implements common functionality used by generated
-// go_marshal tests.
-package analysis
-
-// All functions in this package are unsafe and are not intended for general
-// consumption. They contain sharp edge cases and the caller is responsible for
-// ensuring none of them are hit. Callers must be carefully to pass in only sane
-// arguments. Failure to do so may cause panics at best and arbitrary memory
-// corruption at worst.
-//
-// Never use outside of tests.
-
-import (
- "fmt"
- "math/rand"
- "reflect"
- "testing"
- "unsafe"
-)
-
-// RandomizeValue assigns random value(s) to an abitrary type. This is intended
-// for used with ABI structs from go_marshal, meaning the typical restrictions
-// apply (fixed-size types, no pointers, maps, channels, etc), and should only
-// be used on zeroed values to avoid overwriting pointers to active go objects.
-//
-// Internally, we populate the type with random data by doing an unsafe cast to
-// access the underlying memory of the type and filling it as if it were a byte
-// slice. This almost gets us what we want, but padding fields named "_" are
-// normally not accessible, so we walk the type and recursively zero all "_"
-// fields.
-//
-// Precondition: x must be a pointer. x must not contain any valid
-// pointers to active go objects (pointer fields aren't allowed in ABI
-// structs anyways), or we'd be violating the go runtime contract and
-// the GC may malfunction.
-func RandomizeValue(x interface{}) {
- v := reflect.Indirect(reflect.ValueOf(x))
- if !v.CanSet() {
- panic("RandomizeType() called with an unaddressable value. You probably need to pass a pointer to the argument")
- }
-
- // Cast the underlying memory for the type into a byte slice.
- var b []byte
- hdr := (*reflect.SliceHeader)(unsafe.Pointer(&b))
- // Note: v.UnsafeAddr panics if x is passed by value. x should be a pointer.
- hdr.Data = v.UnsafeAddr()
- hdr.Len = int(v.Type().Size())
- hdr.Cap = hdr.Len
-
- // Fill the byte slice with random data, which in effect fills the type with
- // random values.
- n, err := rand.Read(b)
- if err != nil || n != len(b) {
- panic("unreachable")
- }
-
- // Normally, padding fields are not accessible, so zero them out.
- reflectZeroPaddingFields(v.Type(), b, false)
-}
-
-// reflectZeroPaddingFields assigns zero values to padding fields for the value
-// of type r, represented by the memory in data. Padding fields are defined as
-// fields with the name "_". If zero is true, the immediate value itself is
-// zeroed. In addition, the type is recursively scanned for padding fields in
-// inner types.
-//
-// This is used for zeroing padding fields after calling RandomizeValue.
-func reflectZeroPaddingFields(r reflect.Type, data []byte, zero bool) {
- if zero {
- for i, _ := range data {
- data[i] = 0
- }
- }
- switch r.Kind() {
- case reflect.Int8, reflect.Uint8, reflect.Int16, reflect.Uint16, reflect.Int32, reflect.Uint32, reflect.Int64, reflect.Uint64:
- // These types are explicitly allowed in an ABI type, but we don't need
- // to recurse further as they're scalar types.
- case reflect.Struct:
- for i, numFields := 0, r.NumField(); i < numFields; i++ {
- f := r.Field(i)
- off := f.Offset
- len := f.Type.Size()
- window := data[off : off+len]
- reflectZeroPaddingFields(f.Type, window, f.Name == "_")
- }
- case reflect.Array:
- eLen := int(r.Elem().Size())
- if int(r.Size()) != eLen*r.Len() {
- panic("Array has unexpected size?")
- }
- for i, n := 0, r.Len(); i < n; i++ {
- reflectZeroPaddingFields(r.Elem(), data[i*eLen:(i+1)*eLen], false)
- }
- default:
- panic(fmt.Sprintf("Type %v not allowed in ABI struct", r.Kind()))
-
- }
-}
-
-// AlignmentCheck ensures the definition of the type represented by typ doesn't
-// cause the go compiler to emit implicit padding between elements of the type
-// (i.e. fields in a struct).
-//
-// AlignmentCheck doesn't explicitly recurse for embedded structs because any
-// struct present in an ABI struct must also be Marshallable, and therefore
-// they're aligned by definition (or their alignment check would have failed).
-func AlignmentCheck(t *testing.T, typ reflect.Type) (ok bool, delta uint64) {
- switch typ.Kind() {
- case reflect.Int8, reflect.Uint8, reflect.Int16, reflect.Uint16, reflect.Int32, reflect.Uint32, reflect.Int64, reflect.Uint64:
- // Primitive types are always considered well aligned. Primitive types
- // that are fields in structs are checked independently, this branch
- // exists to handle recursive calls to alignmentCheck.
- case reflect.Struct:
- xOff := 0
- nextXOff := 0
- skipNext := false
- for i, numFields := 0, typ.NumField(); i < numFields; i++ {
- xOff = nextXOff
- f := typ.Field(i)
- fmt.Printf("Checking alignment of %s.%s @ %d [+%d]...\n", typ.Name(), f.Name, f.Offset, f.Type.Size())
- nextXOff = int(f.Offset + f.Type.Size())
-
- if f.Name == "_" {
- // Padding fields need not be aligned.
- fmt.Printf("Padding field of type %v\n", f.Type)
- continue
- }
-
- if tag, ok := f.Tag.Lookup("marshal"); ok && tag == "unaligned" {
- skipNext = true
- continue
- }
-
- if skipNext {
- skipNext = false
- fmt.Printf("Skipping alignment check for field %s.%s explicitly marked as unaligned.\n", typ.Name(), f.Name)
- continue
- }
-
- if xOff != int(f.Offset) {
- implicitPad := int(f.Offset) - xOff
- t.Fatalf("Suspect offset for field %s.%s, detected an implicit %d byte padding from offset %d to %d; either add %d bytes of explicit padding before this field or tag it as `marshal:\"unaligned\"`.", typ.Name(), f.Name, implicitPad, xOff, f.Offset, implicitPad)
- }
- }
-
- // Ensure structs end on a byte explicitly defined by the type.
- if typ.NumField() > 0 && nextXOff != int(typ.Size()) {
- implicitPad := int(typ.Size()) - nextXOff
- f := typ.Field(typ.NumField() - 1) // Final field
- t.Fatalf("Suspect offset for field %s.%s at the end of %s, detected an implicit %d byte padding from offset %d to %d at the end of the struct; either add %d bytes of explict padding at end of the struct or tag the final field %s as `marshal:\"unaligned\"`.",
- typ.Name(), f.Name, typ.Name(), implicitPad, nextXOff, typ.Size(), implicitPad, f.Name)
- }
- case reflect.Array:
- // Independent arrays are also always considered well aligned. We only
- // need to worry about their alignment when they're embedded in structs,
- // which we handle above.
- default:
- t.Fatalf("Unsupported type in ABI struct while checking for field alignment for type: %v", typ.Kind())
- }
- return true, uint64(typ.Size())
-}
diff --git a/tools/go_marshal/defs.bzl b/tools/go_marshal/defs.bzl
deleted file mode 100644
index c32eb559f..000000000
--- a/tools/go_marshal/defs.bzl
+++ /dev/null
@@ -1,152 +0,0 @@
-"""Marshal is a tool for generating marshalling interfaces for Go types.
-
-The recommended way is to use the go_library rule defined below with mostly
-identical configuration as the native go_library rule.
-
-load("//tools/go_marshal:defs.bzl", "go_library")
-
-go_library(
- name = "foo",
- srcs = ["foo.go"],
-)
-
-Under the hood, the go_marshal rule is used to generate a file that will
-appear in a Go target; the output file should appear explicitly in a srcs list.
-For example (the above is still the preferred way):
-
-load("//tools/go_marshal:defs.bzl", "go_marshal")
-
-go_marshal(
- name = "foo_abi",
- srcs = ["foo.go"],
- out = "foo_abi.go",
- package = "foo",
-)
-
-go_library(
- name = "foo",
- srcs = [
- "foo.go",
- "foo_abi.go",
- ],
- deps = [
- "//tools/go_marshal:marshal",
- "//pkg/sentry/platform/safecopy",
- "//pkg/sentry/usermem",
- ],
-)
-"""
-
-load("@io_bazel_rules_go//go:def.bzl", _go_library = "go_library", _go_test = "go_test")
-
-def _go_marshal_impl(ctx):
- """Execute the go_marshal tool."""
- output = ctx.outputs.lib
- output_test = ctx.outputs.test
- (build_dir, _, _) = ctx.build_file_path.rpartition("/BUILD")
-
- decl = "/".join(["gvisor.dev/gvisor", build_dir])
-
- # Run the marshal command.
- args = ["-output=%s" % output.path]
- args += ["-pkg=%s" % ctx.attr.package]
- args += ["-output_test=%s" % output_test.path]
- args += ["-declarationPkg=%s" % decl]
-
- if ctx.attr.debug:
- args += ["-debug"]
-
- args += ["--"]
- for src in ctx.attr.srcs:
- args += [f.path for f in src.files.to_list()]
- ctx.actions.run(
- inputs = ctx.files.srcs,
- outputs = [output, output_test],
- mnemonic = "GoMarshal",
- progress_message = "go_marshal: %s" % ctx.label,
- arguments = args,
- executable = ctx.executable._tool,
- )
-
-# Generates save and restore logic from a set of Go files.
-#
-# Args:
-# name: the name of the rule.
-# srcs: the input source files. These files should include all structs in the
-# package that need to be saved.
-# imports: an optional list of extra, non-aliased, Go-style absolute import
-# paths.
-# out: the name of the generated file output. This must not conflict with any
-# other files and must be added to the srcs of the relevant go_library.
-# package: the package name for the input sources.
-go_marshal = rule(
- implementation = _go_marshal_impl,
- attrs = {
- "srcs": attr.label_list(mandatory = True, allow_files = True),
- "libname": attr.string(mandatory = True),
- "imports": attr.string_list(mandatory = False),
- "package": attr.string(mandatory = True),
- "debug": attr.bool(doc = "enable debugging output from the go_marshal tool"),
- "_tool": attr.label(executable = True, cfg = "host", default = Label("//tools/go_marshal:go_marshal")),
- },
- outputs = {
- "lib": "%{name}_unsafe.go",
- "test": "%{name}_test.go",
- },
-)
-
-def go_library(name, srcs, deps = [], imports = [], debug = False, **kwargs):
- """wraps the standard go_library and does mashalling interface generation.
-
- Args:
- name: Same as native go_library.
- srcs: Same as native go_library.
- deps: Same as native go_library.
- imports: Extra import paths to pass to the go_marshal tool.
- debug: Enables debugging output from the go_marshal tool.
- **kwargs: Remaining args to pass to the native go_library rule unmodified.
- """
- go_marshal(
- name = name + "_abi_autogen",
- libname = name,
- srcs = [src for src in srcs if src.endswith(".go")],
- debug = debug,
- imports = imports,
- package = name,
- )
-
- extra_deps = [
- "//tools/go_marshal/marshal",
- "//pkg/sentry/platform/safecopy",
- "//pkg/sentry/usermem",
- ]
-
- all_srcs = srcs + [name + "_abi_autogen_unsafe.go"]
- all_deps = deps + [] # + extra_deps
-
- for extra in extra_deps:
- if extra not in deps:
- all_deps.append(extra)
-
- _go_library(
- name = name,
- srcs = all_srcs,
- deps = all_deps,
- **kwargs
- )
-
- # Don't pass importpath arg to go_test.
- kwargs.pop("importpath", "")
-
- _go_test(
- name = name + "_abi_autogen_test",
- srcs = [name + "_abi_autogen_test.go"],
- # Generated test has a fixed set of dependencies since we generate these
- # tests. They should only depend on the library generated above, and the
- # Marshallable interface.
- deps = [
- ":" + name,
- "//tools/go_marshal/analysis",
- ],
- **kwargs
- )
diff --git a/tools/go_marshal/gomarshal/BUILD b/tools/go_marshal/gomarshal/BUILD
deleted file mode 100644
index a0eae6492..000000000
--- a/tools/go_marshal/gomarshal/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_library")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "gomarshal",
- srcs = [
- "generator.go",
- "generator_interfaces.go",
- "generator_tests.go",
- "util.go",
- ],
- importpath = "gvisor.dev/gvisor/tools/go_marshal/gomarshal",
- visibility = [
- "//:sandbox",
- ],
-)
diff --git a/tools/go_marshal/gomarshal/generator.go b/tools/go_marshal/gomarshal/generator.go
deleted file mode 100644
index 641ccd938..000000000
--- a/tools/go_marshal/gomarshal/generator.go
+++ /dev/null
@@ -1,382 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package gomarshal implements the go_marshal code generator. See README.md.
-package gomarshal
-
-import (
- "bytes"
- "fmt"
- "go/ast"
- "go/parser"
- "go/token"
- "os"
- "sort"
-)
-
-const (
- marshalImport = "gvisor.dev/gvisor/tools/go_marshal/marshal"
- usermemImport = "gvisor.dev/gvisor/pkg/sentry/usermem"
- safecopyImport = "gvisor.dev/gvisor/pkg/sentry/platform/safecopy"
-)
-
-// List of identifiers we use in generated code, that may conflict a
-// similarly-named source identifier. Avoid problems by refusing the generate
-// code when we see these.
-//
-// This only applies to import aliases at the moment. All other identifiers
-// are qualified by a receiver argument, since they're struct fields.
-//
-// All recievers are single letters, so we don't allow import aliases to be a
-// single letter.
-var badIdents = []string{
- "src", "srcs", "dst", "dsts", "blk", "buf", "err",
- // All single-letter identifiers.
-}
-
-// Generator drives code generation for a single invocation of the go_marshal
-// utility.
-//
-// The Generator holds arguments passed to the tool, and drives parsing,
-// processing and code Generator for all types marked with +marshal declared in
-// the input files.
-//
-// See Generator.run() as the entry point.
-type Generator struct {
- // Paths to input go source files.
- inputs []string
- // Output file to write generated go source.
- output *os.File
- // Output file to write generated tests.
- outputTest *os.File
- // Package name for the generated file.
- pkg string
- // Go import path for package we're processing. This package should directly
- // declare the type we're generating code for.
- declaration string
- // Set of extra packages to import in the generated file.
- imports *importTable
-}
-
-// NewGenerator creates a new code Generator.
-func NewGenerator(srcs []string, out, outTest, pkg, declaration string, imports []string) (*Generator, error) {
- f, err := os.OpenFile(out, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
- if err != nil {
- return nil, fmt.Errorf("Couldn't open output file %q: %v", out, err)
- }
- fTest, err := os.OpenFile(outTest, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
- if err != nil {
- return nil, fmt.Errorf("Couldn't open test output file %q: %v", out, err)
- }
- g := Generator{
- inputs: srcs,
- output: f,
- outputTest: fTest,
- pkg: pkg,
- declaration: declaration,
- imports: newImportTable(),
- }
- for _, i := range imports {
- // All imports on the extra imports list are unconditionally marked as
- // used, so they're always added to the generated code.
- g.imports.add(i).markUsed()
- }
- g.imports.add(marshalImport).markUsed()
- // The follow imports may or may not be used by the generated
- // code, depending what's required for the target types. Don't
- // mark these imports as used by default.
- g.imports.add(usermemImport)
- g.imports.add(safecopyImport)
- g.imports.add("unsafe")
-
- return &g, nil
-}
-
-// writeHeader writes the header for the generated source file. The header
-// includes the package name, package level comments and import statements.
-func (g *Generator) writeHeader() error {
- var b sourceBuffer
- b.emit("// Automatically generated marshal implementation. See tools/go_marshal.\n\n")
- b.emit("package %s\n\n", g.pkg)
- if err := b.write(g.output); err != nil {
- return err
- }
-
- return g.imports.write(g.output)
-}
-
-// writeTypeChecks writes a statement to force the compiler to perform a type
-// check for all Marshallable types referenced by the generated code.
-func (g *Generator) writeTypeChecks(ms map[string]struct{}) error {
- if len(ms) == 0 {
- return nil
- }
-
- msl := make([]string, 0, len(ms))
- for m, _ := range ms {
- msl = append(msl, m)
- }
- sort.Strings(msl)
-
- var buf bytes.Buffer
- fmt.Fprint(&buf, "// Marshallable types used by this file.\n")
-
- for _, m := range msl {
- fmt.Fprintf(&buf, "var _ marshal.Marshallable = (*%s)(nil)\n", m)
- }
- fmt.Fprint(&buf, "\n")
-
- _, err := fmt.Fprint(g.output, buf.String())
- return err
-}
-
-// parse processes all input files passed this generator and produces a set of
-// parsed go ASTs.
-func (g *Generator) parse() ([]*ast.File, []*token.FileSet, error) {
- debugf("go_marshal invoked with %d input files:\n", len(g.inputs))
- for _, path := range g.inputs {
- debugf(" %s\n", path)
- }
-
- files := make([]*ast.File, 0, len(g.inputs))
- fsets := make([]*token.FileSet, 0, len(g.inputs))
-
- for _, path := range g.inputs {
- fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
- if err != nil {
- // Not a valid input file?
- return nil, nil, fmt.Errorf("Input %q can't be parsed: %v", path, err)
- }
-
- if debugEnabled() {
- debugf("AST for %q:\n", path)
- ast.Print(fset, f)
- }
-
- files = append(files, f)
- fsets = append(fsets, fset)
- }
-
- return files, fsets, nil
-}
-
-// collectMarshallabeTypes walks the parsed AST and collects a list of type
-// declarations for which we need to generate the Marshallable interface.
-func (g *Generator) collectMarshallabeTypes(a *ast.File, f *token.FileSet) []*ast.TypeSpec {
- var types []*ast.TypeSpec
- for _, decl := range a.Decls {
- gdecl, ok := decl.(*ast.GenDecl)
- // Type declaration?
- if !ok || gdecl.Tok != token.TYPE {
- debugfAt(f.Position(decl.Pos()), "Skipping declaration since it's not a type declaration.\n")
- continue
- }
- // Does it have a comment?
- if gdecl.Doc == nil {
- debugfAt(f.Position(gdecl.Pos()), "Skipping declaration since it doesn't have a comment.\n")
- continue
- }
- // Does the comment contain a "+marshal" line?
- marked := false
- for _, c := range gdecl.Doc.List {
- if c.Text == "// +marshal" {
- marked = true
- break
- }
- }
- if !marked {
- debugfAt(f.Position(gdecl.Pos()), "Skipping declaration since it doesn't have a comment containing +marshal line.\n")
- continue
- }
- for _, spec := range gdecl.Specs {
- // We already confirmed we're in a type declaration earlier.
- t := spec.(*ast.TypeSpec)
- if _, ok := t.Type.(*ast.StructType); ok {
- debugfAt(f.Position(t.Pos()), "Collected marshallable type %s.\n", t.Name.Name)
- types = append(types, t)
- continue
- }
- debugf("Skipping declaration %v since it's not a struct declaration.\n", gdecl)
- }
- }
- return types
-}
-
-// collectImports collects all imports from all input source files. Some of
-// these imports are copied to the generated output, if they're referenced by
-// the generated code.
-//
-// collectImports de-duplicates imports while building the list, and ensures
-// identifiers in the generated code don't conflict with any imported package
-// names.
-func (g *Generator) collectImports(a *ast.File, f *token.FileSet) map[string]importStmt {
- badImportNames := make(map[string]bool)
- for _, i := range badIdents {
- badImportNames[i] = true
- }
-
- is := make(map[string]importStmt)
- for _, decl := range a.Decls {
- gdecl, ok := decl.(*ast.GenDecl)
- // Import statement?
- if !ok || gdecl.Tok != token.IMPORT {
- continue
- }
- for _, spec := range gdecl.Specs {
- i := g.imports.addFromSpec(spec.(*ast.ImportSpec), f)
- debugf("Collected import '%s' as '%s'\n", i.path, i.name)
-
- // Make sure we have an import that doesn't use any local names that
- // would conflict with identifiers in the generated code.
- if len(i.name) == 1 {
- abortAt(f.Position(spec.Pos()), fmt.Sprintf("Import has a single character local name '%s'; this may conflict with code generated by go_marshal, use a multi-character import alias", i.name))
- }
- if badImportNames[i.name] {
- abortAt(f.Position(spec.Pos()), fmt.Sprintf("Import name '%s' is likely to conflict with code generated by go_marshal, use a different import alias", i.name))
- }
- }
- }
- return is
-
-}
-
-func (g *Generator) generateOne(t *ast.TypeSpec, fset *token.FileSet) *interfaceGenerator {
- // We're guaranteed to have only struct type specs by now. See
- // Generator.collectMarshallabeTypes.
- i := newInterfaceGenerator(t, fset)
- i.validate()
- i.emitMarshallable()
- return i
-}
-
-// generateOneTestSuite generates a test suite for the automatically generated
-// implementations type t.
-func (g *Generator) generateOneTestSuite(t *ast.TypeSpec) *testGenerator {
- i := newTestGenerator(t, g.declaration)
- i.emitTests()
- return i
-}
-
-// Run is the entry point to code generation using g.
-//
-// Run parses all input source files specified in g and emits generated code.
-func (g *Generator) Run() error {
- // Parse our input source files into ASTs and token sets.
- asts, fsets, err := g.parse()
- if err != nil {
- return err
- }
-
- if len(asts) != len(fsets) {
- panic("ASTs and FileSets don't match")
- }
-
- // Map of imports in source files; key = local package name, value = import
- // path.
- is := make(map[string]importStmt)
- for i, a := range asts {
- // Collect all imports from the source files. We may need to copy some
- // of these to the generated code if they're referenced. This has to be
- // done before the loop below because we need to process all ASTs before
- // we start requesting imports to be copied one by one as we encounter
- // them in each generated source.
- for name, i := range g.collectImports(a, fsets[i]) {
- is[name] = i
- }
- }
-
- var impls []*interfaceGenerator
- var ts []*testGenerator
- // Set of Marshallable types referenced by generated code.
- ms := make(map[string]struct{})
- for i, a := range asts {
- // Collect type declarations marked for code generation and generate
- // Marshallable interfaces.
- for _, t := range g.collectMarshallabeTypes(a, fsets[i]) {
- impl := g.generateOne(t, fsets[i])
- // Collect Marshallable types referenced by the generated code.
- for ref, _ := range impl.ms {
- ms[ref] = struct{}{}
- }
- impls = append(impls, impl)
- // Collect imports referenced by the generated code and add them to
- // the list of imports we need to copy to the generated code.
- for name, _ := range impl.is {
- if !g.imports.markUsed(name) {
- panic(fmt.Sprintf("Generated code for '%s' referenced a non-existent import with local name '%s'", impl.typeName(), name))
- }
- }
- ts = append(ts, g.generateOneTestSuite(t))
- }
- }
-
- // Tool was invoked with input files with no data structures marked for code
- // generation. This is probably not what the user intended.
- if len(impls) == 0 {
- var buf bytes.Buffer
- fmt.Fprintf(&buf, "go_marshal invoked on these files, but they don't contain any types requiring code generation. Perhaps mark some with \"// +marshal\"?:\n")
- for _, i := range g.inputs {
- fmt.Fprintf(&buf, " %s\n", i)
- }
- abort(buf.String())
- }
-
- // Write output file header. These include things like package name and
- // import statements.
- if err := g.writeHeader(); err != nil {
- return err
- }
-
- // Write type checks for referenced marshallable types to output file.
- if err := g.writeTypeChecks(ms); err != nil {
- return err
- }
-
- // Write generated interfaces to output file.
- for _, i := range impls {
- if err := i.write(g.output); err != nil {
- return err
- }
- }
-
- // Write generated tests to test file.
- return g.writeTests(ts)
-}
-
-// writeTests outputs tests for the generated interface implementations to a go
-// source file.
-func (g *Generator) writeTests(ts []*testGenerator) error {
- var b sourceBuffer
- b.emit("package %s_test\n\n", g.pkg)
- if err := b.write(g.outputTest); err != nil {
- return err
- }
-
- imports := newImportTable()
- for _, t := range ts {
- imports.merge(t.imports)
- }
-
- if err := imports.write(g.outputTest); err != nil {
- return err
- }
-
- for _, t := range ts {
- if err := t.write(g.outputTest); err != nil {
- return err
- }
- }
- return nil
-}
diff --git a/tools/go_marshal/gomarshal/generator_interfaces.go b/tools/go_marshal/gomarshal/generator_interfaces.go
deleted file mode 100644
index a712c14dc..000000000
--- a/tools/go_marshal/gomarshal/generator_interfaces.go
+++ /dev/null
@@ -1,507 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package gomarshal
-
-import (
- "fmt"
- "go/ast"
- "go/token"
- "strings"
-)
-
-// interfaceGenerator generates marshalling interfaces for a single type.
-//
-// getState is not thread-safe.
-type interfaceGenerator struct {
- sourceBuffer
-
- // The type we're serializing.
- t *ast.TypeSpec
-
- // Receiver argument for generated methods.
- r string
-
- // FileSet containing the tokens for the type we're processing.
- f *token.FileSet
-
- // is records external packages referenced by the generated implementation.
- is map[string]struct{}
-
- // ms records Marshallable types referenced by the generated implementation
- // of t's interfaces.
- ms map[string]struct{}
-
- // as records embedded fields in t that are potentially not packed. The key
- // is the accessor for the field.
- as map[string]struct{}
-}
-
-// typeName returns the name of the type this g represents.
-func (g *interfaceGenerator) typeName() string {
- return g.t.Name.Name
-}
-
-// newinterfaceGenerator creates a new interface generator.
-func newInterfaceGenerator(t *ast.TypeSpec, fset *token.FileSet) *interfaceGenerator {
- if _, ok := t.Type.(*ast.StructType); !ok {
- panic(fmt.Sprintf("Attempting to generate code for a not struct type %v", t))
- }
- g := &interfaceGenerator{
- t: t,
- r: receiverName(t),
- f: fset,
- is: make(map[string]struct{}),
- ms: make(map[string]struct{}),
- as: make(map[string]struct{}),
- }
- g.recordUsedMarshallable(g.typeName())
- return g
-}
-
-func (g *interfaceGenerator) recordUsedMarshallable(m string) {
- g.ms[m] = struct{}{}
-
-}
-
-func (g *interfaceGenerator) recordUsedImport(i string) {
- g.is[i] = struct{}{}
-
-}
-
-func (g *interfaceGenerator) recordPotentiallyNonPackedField(fieldName string) {
- g.as[fieldName] = struct{}{}
-}
-
-func (g *interfaceGenerator) forEachField(fn func(f *ast.Field)) {
- // This is guaranteed to succeed because g.t is always a struct.
- st := g.t.Type.(*ast.StructType)
- for _, field := range st.Fields.List {
- fn(field)
- }
-}
-
-func (g *interfaceGenerator) fieldAccessor(n *ast.Ident) string {
- return fmt.Sprintf("%s.%s", g.r, n.Name)
-}
-
-// abortAt aborts the go_marshal tool with the given error message, with a
-// reference position to the input source. Same as abortAt, but uses g to
-// resolve p to position.
-func (g *interfaceGenerator) abortAt(p token.Pos, msg string) {
- abortAt(g.f.Position(p), msg)
-}
-
-// validate ensures the type we're working with can be marshalled. These checks
-// are done ahead of time and in one place so we can make assumptions later.
-func (g *interfaceGenerator) validate() {
- g.forEachField(func(f *ast.Field) {
- if len(f.Names) == 0 {
- g.abortAt(f.Pos(), "Cannot marshal structs with embedded fields, give the field a name; use '_' for anonymous fields such as padding fields")
- }
- })
-
- g.forEachField(func(f *ast.Field) {
- fieldDispatcher{
- primitive: func(_, t *ast.Ident) {
- switch t.Name {
- case "int8", "uint8", "byte", "int16", "uint16", "int32", "uint32", "int64", "uint64":
- // These are the only primitive types we're allow. Below, we
- // provide suggestions for some disallowed types and reject
- // them, then attempt to marshal any remaining types by
- // invoking the marshal.Marshallable interface on them. If
- // these types don't actually implement
- // marshal.Marshallable, compilation of the generated code
- // will fail with an appropriate error message.
- return
- case "int":
- g.abortAt(f.Pos(), "Type 'int' has ambiguous width, use int32 or int64")
- case "uint":
- g.abortAt(f.Pos(), "Type 'uint' has ambiguous width, use uint32 or uint64")
- case "string":
- g.abortAt(f.Pos(), "Type 'string' is dynamically-sized and cannot be marshalled, use a fixed size byte array '[...]byte' instead")
- default:
- debugfAt(g.f.Position(f.Pos()), fmt.Sprintf("Found derived type '%s', will attempt dispatch via marshal.Marshallable.\n", t.Name))
- }
- },
- selector: func(_, _, _ *ast.Ident) {
- // No validation to perform on selector fields. However this
- // callback must still be provided.
- },
- array: func(n, _ *ast.Ident, len int) {
- a := f.Type.(*ast.ArrayType)
- if a.Len == nil {
- g.abortAt(f.Pos(), fmt.Sprintf("Dynamically sized slice '%s' cannot be marshalled, arrays must be statically sized", n.Name))
- }
-
- if _, ok := a.Len.(*ast.BasicLit); !ok {
- g.abortAt(a.Len.Pos(), fmt.Sprintf("Array size must be a literal, don's use consts or expressions"))
- }
-
- if _, ok := a.Elt.(*ast.Ident); !ok {
- g.abortAt(a.Elt.Pos(), fmt.Sprintf("Marshalling not supported for arrays with %s elements, array elements must be primitive types", kindString(a.Elt)))
- }
-
- if len <= 0 {
- g.abortAt(a.Len.Pos(), fmt.Sprintf("Marshalling not supported for zero length arrays, why does an ABI struct have one?"))
- }
- },
- unhandled: func(_ *ast.Ident) {
- g.abortAt(f.Pos(), fmt.Sprintf("Marshalling not supported for %s fields", kindString(f.Type)))
- },
- }.dispatch(f)
- })
-}
-
-// scalarSize returns the size of type identified by t. If t isn't a primitive
-// type, the size isn't known at code generation time, and must be resolved via
-// the marshal.Marshallable interface.
-func (g *interfaceGenerator) scalarSize(t *ast.Ident) (size int, unknownSize bool) {
- switch t.Name {
- case "int8", "uint8", "byte":
- return 1, false
- case "int16", "uint16":
- return 2, false
- case "int32", "uint32":
- return 4, false
- case "int64", "uint64":
- return 8, false
- default:
- return 0, true
- }
-}
-
-func (g *interfaceGenerator) shift(bufVar string, n int) {
- g.emit("%s = %s[%d:]\n", bufVar, bufVar, n)
-}
-
-func (g *interfaceGenerator) shiftDynamic(bufVar, name string) {
- g.emit("%s = %s[%s.SizeBytes():]\n", bufVar, bufVar, name)
-}
-
-func (g *interfaceGenerator) marshalScalar(accessor, typ string, bufVar string) {
- switch typ {
- case "int8", "uint8", "byte":
- g.emit("%s[0] = byte(%s)\n", bufVar, accessor)
- g.shift(bufVar, 1)
- case "int16", "uint16":
- g.recordUsedImport("usermem")
- g.emit("usermem.ByteOrder.PutUint16(%s[:2], uint16(%s))\n", bufVar, accessor)
- g.shift(bufVar, 2)
- case "int32", "uint32":
- g.recordUsedImport("usermem")
- g.emit("usermem.ByteOrder.PutUint32(%s[:4], uint32(%s))\n", bufVar, accessor)
- g.shift(bufVar, 4)
- case "int64", "uint64":
- g.recordUsedImport("usermem")
- g.emit("usermem.ByteOrder.PutUint64(%s[:8], uint64(%s))\n", bufVar, accessor)
- g.shift(bufVar, 8)
- default:
- g.emit("%s.MarshalBytes(%s[:%s.SizeBytes()])\n", accessor, bufVar, accessor)
- g.shiftDynamic(bufVar, accessor)
- }
-}
-
-func (g *interfaceGenerator) unmarshalScalar(accessor, typ string, bufVar string) {
- switch typ {
- case "int8":
- g.emit("%s = int8(%s[0])\n", accessor, bufVar)
- g.shift(bufVar, 1)
- case "uint8":
- g.emit("%s = uint8(%s[0])\n", accessor, bufVar)
- g.shift(bufVar, 1)
- case "byte":
- g.emit("%s = %s[0]\n", accessor, bufVar)
- g.shift(bufVar, 1)
-
- case "int16":
- g.recordUsedImport("usermem")
- g.emit("%s = int16(usermem.ByteOrder.Uint16(%s[:2]))\n", accessor, bufVar)
- g.shift(bufVar, 2)
- case "uint16":
- g.recordUsedImport("usermem")
- g.emit("%s = usermem.ByteOrder.Uint16(%s[:2])\n", accessor, bufVar)
- g.shift(bufVar, 2)
-
- case "int32":
- g.recordUsedImport("usermem")
- g.emit("%s = int32(usermem.ByteOrder.Uint32(%s[:4]))\n", accessor, bufVar)
- g.shift(bufVar, 4)
- case "uint32":
- g.recordUsedImport("usermem")
- g.emit("%s = usermem.ByteOrder.Uint32(%s[:4])\n", accessor, bufVar)
- g.shift(bufVar, 4)
-
- case "int64":
- g.recordUsedImport("usermem")
- g.emit("%s = int64(usermem.ByteOrder.Uint64(%s[:8]))\n", accessor, bufVar)
- g.shift(bufVar, 8)
- case "uint64":
- g.recordUsedImport("usermem")
- g.emit("%s = usermem.ByteOrder.Uint64(%s[:8])\n", accessor, bufVar)
- g.shift(bufVar, 8)
- default:
- g.emit("%s.UnmarshalBytes(%s[:%s.SizeBytes()])\n", accessor, bufVar, accessor)
- g.shiftDynamic(bufVar, accessor)
- g.recordPotentiallyNonPackedField(accessor)
- }
-}
-
-// areFieldsPackedExpression returns a go expression checking whether g.t's fields are
-// packed. Returns "", false if g.t has no fields that may be potentially
-// packed, otherwise returns <clause>, true, where <clause> is an expression
-// like "t.a.Packed() && t.b.Packed() && t.c.Packed()".
-func (g *interfaceGenerator) areFieldsPackedExpression() (string, bool) {
- if len(g.as) == 0 {
- return "", false
- }
-
- cs := make([]string, 0, len(g.as))
- for accessor, _ := range g.as {
- cs = append(cs, fmt.Sprintf("%s.Packed()", accessor))
- }
- return strings.Join(cs, " && "), true
-}
-
-func (g *interfaceGenerator) emitMarshallable() {
- // Is g.t a packed struct without consideing field types?
- thisPacked := true
- g.forEachField(func(f *ast.Field) {
- if f.Tag != nil {
- if f.Tag.Value == "`marshal:\"unaligned\"`" {
- if thisPacked {
- debugfAt(g.f.Position(g.t.Pos()),
- fmt.Sprintf("Marking type '%s' as not packed due to tag `marshal:\"unaligned\"`.\n", g.t.Name))
- thisPacked = false
- }
- }
- }
- })
-
- g.emit("// SizeBytes implements marshal.Marshallable.SizeBytes.\n")
- g.emit("func (%s *%s) SizeBytes() int {\n", g.r, g.typeName())
- g.inIndent(func() {
- primitiveSize := 0
- var dynamicSizeTerms []string
-
- g.forEachField(fieldDispatcher{
- primitive: func(n, t *ast.Ident) {
- if size, dynamic := g.scalarSize(t); !dynamic {
- primitiveSize += size
- } else {
- g.recordUsedMarshallable(t.Name)
- dynamicSizeTerms = append(dynamicSizeTerms, fmt.Sprintf("%s.SizeBytes()", g.fieldAccessor(n)))
- }
- },
- selector: func(n, tX, tSel *ast.Ident) {
- tName := fmt.Sprintf("%s.%s", tX.Name, tSel.Name)
- g.recordUsedImport(tX.Name)
- g.recordUsedMarshallable(tName)
- dynamicSizeTerms = append(dynamicSizeTerms, fmt.Sprintf("(*%s)(nil).SizeBytes()", tName))
- },
- array: func(n, t *ast.Ident, len int) {
- if len < 1 {
- // Zero-length arrays should've been rejected by validate().
- panic("unreachable")
- }
- if size, dynamic := g.scalarSize(t); !dynamic {
- primitiveSize += size * len
- } else {
- g.recordUsedMarshallable(t.Name)
- dynamicSizeTerms = append(dynamicSizeTerms, fmt.Sprintf("(*%s)(nil).SizeBytes()*%d", t.Name, len))
- }
- },
- }.dispatch)
- g.emit("return %d", primitiveSize)
- if len(dynamicSizeTerms) > 0 {
- g.incIndent()
- }
- {
- for _, d := range dynamicSizeTerms {
- g.emitNoIndent(" +\n")
- g.emit(d)
- }
- }
- if len(dynamicSizeTerms) > 0 {
- g.decIndent()
- }
- })
- g.emit("\n}\n\n")
-
- g.emit("// MarshalBytes implements marshal.Marshallable.MarshalBytes.\n")
- g.emit("func (%s *%s) MarshalBytes(dst []byte) {\n", g.r, g.typeName())
- g.inIndent(func() {
- g.forEachField(fieldDispatcher{
- primitive: func(n, t *ast.Ident) {
- if n.Name == "_" {
- g.emit("// Padding: dst[:sizeof(%s)] ~= %s(0)\n", t.Name, t.Name)
- if len, dynamic := g.scalarSize(t); !dynamic {
- g.shift("dst", len)
- } else {
- // We can't use shiftDynamic here because we don't have
- // an instance of the dynamic type we can referece here
- // (since the version in this struct is anonymous). Use
- // a typed nil pointer to call SizeBytes() instead.
- g.emit("dst = dst[(*%s)(nil).SizeBytes():]\n", t.Name)
- }
- return
- }
- g.marshalScalar(g.fieldAccessor(n), t.Name, "dst")
- },
- selector: func(n, tX, tSel *ast.Ident) {
- g.marshalScalar(g.fieldAccessor(n), fmt.Sprintf("%s.%s", tX.Name, tSel.Name), "dst")
- },
- array: func(n, t *ast.Ident, size int) {
- if n.Name == "_" {
- g.emit("// Padding: dst[:sizeof(%s)*%d] ~= [%d]%s{0}\n", t.Name, size, size, t.Name)
- if len, dynamic := g.scalarSize(t); !dynamic {
- g.shift("dst", len*size)
- } else {
- // We can't use shiftDynamic here because we don't have
- // an instance of the dynamic type we can reference here
- // (since the version in this struct is anonymous). Use
- // a typed nil pointer to call SizeBytes() instead.
- g.emit("dst = dst[(*%s)(nil).SizeBytes()*%d:]\n", t.Name, size)
- }
- return
- }
-
- g.emit("for i := 0; i < %d; i++ {\n", size)
- g.inIndent(func() {
- g.marshalScalar(fmt.Sprintf("%s[i]", g.fieldAccessor(n)), t.Name, "dst")
- })
- g.emit("}\n")
- },
- }.dispatch)
- })
- g.emit("}\n\n")
-
- g.emit("// UnmarshalBytes implements marshal.Marshallable.UnmarshalBytes.\n")
- g.emit("func (%s *%s) UnmarshalBytes(src []byte) {\n", g.r, g.typeName())
- g.inIndent(func() {
- g.forEachField(fieldDispatcher{
- primitive: func(n, t *ast.Ident) {
- if n.Name == "_" {
- g.emit("// Padding: var _ %s ~= src[:sizeof(%s)]\n", t.Name, t.Name)
- if len, dynamic := g.scalarSize(t); !dynamic {
- g.shift("src", len)
- } else {
- // We can't use shiftDynamic here because we don't have
- // an instance of the dynamic type we can reference here
- // (since the version in this struct is anonymous). Use
- // a typed nil pointer to call SizeBytes() instead.
- g.emit("src = src[(*%s)(nil).SizeBytes():]\n", t.Name)
- g.recordPotentiallyNonPackedField(fmt.Sprintf("(*%s)(nil)", t.Name))
- }
- return
- }
- g.unmarshalScalar(g.fieldAccessor(n), t.Name, "src")
- },
- selector: func(n, tX, tSel *ast.Ident) {
- g.unmarshalScalar(g.fieldAccessor(n), fmt.Sprintf("%s.%s", tX.Name, tSel.Name), "src")
- },
- array: func(n, t *ast.Ident, size int) {
- if n.Name == "_" {
- g.emit("// Padding: ~ copy([%d]%s(%s), src[:sizeof(%s)*%d])\n", size, t.Name, g.fieldAccessor(n), t.Name, size)
- if len, dynamic := g.scalarSize(t); !dynamic {
- g.shift("src", len*size)
- } else {
- // We can't use shiftDynamic here because we don't have
- // an instance of the dynamic type we can referece here
- // (since the version in this struct is anonymous). Use
- // a typed nil pointer to call SizeBytes() instead.
- g.emit("src = src[(*%s)(nil).SizeBytes()*%d:]\n", t.Name, size)
- }
- return
- }
-
- g.emit("for i := 0; i < %d; i++ {\n", size)
- g.inIndent(func() {
- g.unmarshalScalar(fmt.Sprintf("%s[i]", g.fieldAccessor(n)), t.Name, "src")
- })
- g.emit("}\n")
- },
- }.dispatch)
- })
- g.emit("}\n\n")
-
- g.emit("// Packed implements marshal.Marshallable.Packed.\n")
- g.emit("func (%s *%s) Packed() bool {\n", g.r, g.typeName())
- g.inIndent(func() {
- expr, fieldsMaybePacked := g.areFieldsPackedExpression()
- switch {
- case !thisPacked:
- g.emit("return false\n")
- case fieldsMaybePacked:
- g.emit("return %s\n", expr)
- default:
- g.emit("return true\n")
-
- }
- })
- g.emit("}\n\n")
-
- g.emit("// MarshalUnsafe implements marshal.Marshallable.MarshalUnsafe.\n")
- g.emit("func (%s *%s) MarshalUnsafe(dst []byte) {\n", g.r, g.typeName())
- g.inIndent(func() {
- if thisPacked {
- g.recordUsedImport("safecopy")
- g.recordUsedImport("unsafe")
- if cond, ok := g.areFieldsPackedExpression(); ok {
- g.emit("if %s {\n", cond)
- g.inIndent(func() {
- g.emit("safecopy.CopyIn(dst, unsafe.Pointer(%s))\n", g.r)
- })
- g.emit("} else {\n")
- g.inIndent(func() {
- g.emit("%s.MarshalBytes(dst)\n", g.r)
- })
- g.emit("}\n")
- } else {
- g.emit("safecopy.CopyIn(dst, unsafe.Pointer(%s))\n", g.r)
- }
- } else {
- g.emit("// Type %s doesn't have a packed layout in memory, fallback to MarshalBytes.\n", g.typeName())
- g.emit("%s.MarshalBytes(dst)\n", g.r)
- }
- })
- g.emit("}\n\n")
-
- g.emit("// UnmarshalUnsafe implements marshal.Marshallable.UnmarshalUnsafe.\n")
- g.emit("func (%s *%s) UnmarshalUnsafe(src []byte) {\n", g.r, g.typeName())
- g.inIndent(func() {
- if thisPacked {
- g.recordUsedImport("safecopy")
- g.recordUsedImport("unsafe")
- if cond, ok := g.areFieldsPackedExpression(); ok {
- g.emit("if %s {\n", cond)
- g.inIndent(func() {
- g.emit("safecopy.CopyOut(unsafe.Pointer(%s), src)\n", g.r)
- })
- g.emit("} else {\n")
- g.inIndent(func() {
- g.emit("%s.UnmarshalBytes(src)\n", g.r)
- })
- g.emit("}\n")
- } else {
- g.emit("safecopy.CopyOut(unsafe.Pointer(%s), src)\n", g.r)
- }
- } else {
- g.emit("// Type %s doesn't have a packed layout in memory, fall back to UnmarshalBytes.\n", g.typeName())
- g.emit("%s.UnmarshalBytes(src)\n", g.r)
- }
- })
- g.emit("}\n\n")
-
-}
diff --git a/tools/go_marshal/gomarshal/generator_tests.go b/tools/go_marshal/gomarshal/generator_tests.go
deleted file mode 100644
index df25cb5b2..000000000
--- a/tools/go_marshal/gomarshal/generator_tests.go
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package gomarshal
-
-import (
- "fmt"
- "go/ast"
- "io"
- "strings"
-)
-
-var standardImports = []string{
- "fmt",
- "reflect",
- "testing",
- "gvisor.dev/gvisor/tools/go_marshal/analysis",
-}
-
-type testGenerator struct {
- sourceBuffer
-
- // The type we're serializing.
- t *ast.TypeSpec
-
- // Receiver argument for generated methods.
- r string
-
- // Imports used by generated code.
- imports *importTable
-
- // Import statement for the package declaring the type we generated code
- // for. We need this to construct test instances for the type, since the
- // tests aren't written in the same package.
- decl *importStmt
-}
-
-func newTestGenerator(t *ast.TypeSpec, declaration string) *testGenerator {
- if _, ok := t.Type.(*ast.StructType); !ok {
- panic(fmt.Sprintf("Attempting to generate code for a not struct type %v", t))
- }
- g := &testGenerator{
- t: t,
- r: receiverName(t),
- imports: newImportTable(),
- }
-
- for _, i := range standardImports {
- g.imports.add(i).markUsed()
- }
- g.decl = g.imports.add(declaration)
- g.decl.markUsed()
-
- return g
-}
-
-func (g *testGenerator) typeName() string {
- return fmt.Sprintf("%s.%s", g.decl.name, g.t.Name.Name)
-}
-
-func (g *testGenerator) forEachField(fn func(f *ast.Field)) {
- // This is guaranteed to succeed because g.t is always a struct.
- st := g.t.Type.(*ast.StructType)
- for _, field := range st.Fields.List {
- fn(field)
- }
-}
-
-func (g *testGenerator) testFuncName(base string) string {
- return fmt.Sprintf("%s%s", base, strings.Title(g.t.Name.Name))
-}
-
-func (g *testGenerator) inTestFunction(name string, body func()) {
- g.emit("func %s(t *testing.T) {\n", g.testFuncName(name))
- g.inIndent(body)
- g.emit("}\n\n")
-}
-
-func (g *testGenerator) emitTestNonZeroSize() {
- g.inTestFunction("TestSizeNonZero", func() {
- g.emit("x := &%s{}\n", g.typeName())
- g.emit("if x.SizeBytes() == 0 {\n")
- g.inIndent(func() {
- g.emit("t.Fatal(\"Marshallable.Size() should not return zero\")\n")
- })
- g.emit("}\n")
- })
-}
-
-func (g *testGenerator) emitTestSuspectAlignment() {
- g.inTestFunction("TestSuspectAlignment", func() {
- g.emit("x := %s{}\n", g.typeName())
- g.emit("analysis.AlignmentCheck(t, reflect.TypeOf(x))\n")
- })
-}
-
-func (g *testGenerator) emitTestMarshalUnmarshalPreservesData() {
- g.inTestFunction("TestSafeMarshalUnmarshalPreservesData", func() {
- g.emit("var x, y, z, yUnsafe, zUnsafe %s\n", g.typeName())
- g.emit("analysis.RandomizeValue(&x)\n\n")
-
- g.emit("buf := make([]byte, x.SizeBytes())\n")
- g.emit("x.MarshalBytes(buf)\n")
- g.emit("bufUnsafe := make([]byte, x.SizeBytes())\n")
- g.emit("x.MarshalUnsafe(bufUnsafe)\n\n")
-
- g.emit("y.UnmarshalBytes(buf)\n")
- g.emit("if !reflect.DeepEqual(x, y) {\n")
- g.inIndent(func() {
- g.emit("t.Fatal(fmt.Sprintf(\"Data corrupted across Marshal/Unmarshal cycle:\\nBefore: %%+v\\nAfter: %%+v\\n\", x, y))\n")
- })
- g.emit("}\n")
- g.emit("yUnsafe.UnmarshalBytes(bufUnsafe)\n")
- g.emit("if !reflect.DeepEqual(x, yUnsafe) {\n")
- g.inIndent(func() {
- g.emit("t.Fatal(fmt.Sprintf(\"Data corrupted across MarshalUnsafe/Unmarshal cycle:\\nBefore: %%+v\\nAfter: %%+v\\n\", x, yUnsafe))\n")
- })
- g.emit("}\n\n")
-
- g.emit("z.UnmarshalUnsafe(buf)\n")
- g.emit("if !reflect.DeepEqual(x, z) {\n")
- g.inIndent(func() {
- g.emit("t.Fatal(fmt.Sprintf(\"Data corrupted across Marshal/UnmarshalUnsafe cycle:\\nBefore: %%+v\\nAfter: %%+v\\n\", x, z))\n")
- })
- g.emit("}\n")
- g.emit("zUnsafe.UnmarshalUnsafe(bufUnsafe)\n")
- g.emit("if !reflect.DeepEqual(x, zUnsafe) {\n")
- g.inIndent(func() {
- g.emit("t.Fatal(fmt.Sprintf(\"Data corrupted across MarshalUnsafe/UnmarshalUnsafe cycle:\\nBefore: %%+v\\nAfter: %%+v\\n\", x, zUnsafe))\n")
- })
- g.emit("}\n")
- })
-}
-
-func (g *testGenerator) emitTests() {
- g.emitTestNonZeroSize()
- g.emitTestSuspectAlignment()
- g.emitTestMarshalUnmarshalPreservesData()
-}
-
-func (g *testGenerator) write(out io.Writer) error {
- return g.sourceBuffer.write(out)
-}
diff --git a/tools/go_marshal/gomarshal/util.go b/tools/go_marshal/gomarshal/util.go
deleted file mode 100644
index 967537abf..000000000
--- a/tools/go_marshal/gomarshal/util.go
+++ /dev/null
@@ -1,387 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package gomarshal
-
-import (
- "bytes"
- "flag"
- "fmt"
- "go/ast"
- "go/token"
- "io"
- "os"
- "path"
- "reflect"
- "sort"
- "strconv"
- "strings"
-)
-
-var debug = flag.Bool("debug", false, "enables debugging output")
-
-// receiverName returns an appropriate receiver name given a type spec.
-func receiverName(t *ast.TypeSpec) string {
- if len(t.Name.Name) < 1 {
- // Zero length type name?
- panic("unreachable")
- }
- return strings.ToLower(t.Name.Name[:1])
-}
-
-// kindString returns a user-friendly representation of an AST expr type.
-func kindString(e ast.Expr) string {
- switch e.(type) {
- case *ast.Ident:
- return "scalar"
- case *ast.ArrayType:
- return "array"
- case *ast.StructType:
- return "struct"
- case *ast.StarExpr:
- return "pointer"
- case *ast.FuncType:
- return "function"
- case *ast.InterfaceType:
- return "interface"
- case *ast.MapType:
- return "map"
- case *ast.ChanType:
- return "channel"
- default:
- return reflect.TypeOf(e).String()
- }
-}
-
-// fieldDispatcher is a collection of callbacks for handling different types of
-// fields in a struct declaration.
-type fieldDispatcher struct {
- primitive func(n, t *ast.Ident)
- selector func(n, tX, tSel *ast.Ident)
- array func(n, t *ast.Ident, size int)
- unhandled func(n *ast.Ident)
-}
-
-// Precondition: All dispatch callbacks that will be invoked must be
-// provided. Embedded fields are not allowed, len(f.Names) >= 1.
-func (fd fieldDispatcher) dispatch(f *ast.Field) {
- // Each field declaration may actually be multiple declarations of the same
- // type. For example, consider:
- //
- // type Point struct {
- // x, y, z int
- // }
- //
- // We invoke the call-backs once per such instance. Embedded fields are not
- // allowed, and results in a panic.
- if len(f.Names) < 1 {
- panic("Precondition not met: attempted to dispatch on embedded field")
- }
-
- for _, name := range f.Names {
- switch v := f.Type.(type) {
- case *ast.Ident:
- fd.primitive(name, v)
- case *ast.SelectorExpr:
- fd.selector(name, v.X.(*ast.Ident), v.Sel)
- case *ast.ArrayType:
- len := 0
- if v.Len != nil {
- // Non-literal array length is handled by generatorInterfaces.validate().
- if lenLit, ok := v.Len.(*ast.BasicLit); ok {
- var err error
- len, err = strconv.Atoi(lenLit.Value)
- if err != nil {
- panic(err)
- }
- }
- }
- switch t := v.Elt.(type) {
- case *ast.Ident:
- fd.array(name, t, len)
- default:
- fd.array(name, nil, len)
- }
- default:
- fd.unhandled(name)
- }
- }
-}
-
-// debugEnabled indicates whether debugging is enabled for gomarshal.
-func debugEnabled() bool {
- return *debug
-}
-
-// abort aborts the go_marshal tool with the given error message.
-func abort(msg string) {
- if !strings.HasSuffix(msg, "\n") {
- msg += "\n"
- }
- fmt.Print(msg)
- os.Exit(1)
-}
-
-// abortAt aborts the go_marshal tool with the given error message, with
-// a reference position to the input source.
-func abortAt(p token.Position, msg string) {
- abort(fmt.Sprintf("%v:\n %s\n", p, msg))
-}
-
-// debugf conditionally prints a debug message.
-func debugf(f string, a ...interface{}) {
- if debugEnabled() {
- fmt.Printf(f, a...)
- }
-}
-
-// debugfAt conditionally prints a debug message with a reference to a position
-// in the input source.
-func debugfAt(p token.Position, f string, a ...interface{}) {
- if debugEnabled() {
- fmt.Printf("%s:\n %s", p, fmt.Sprintf(f, a...))
- }
-}
-
-// emit generates a line of code in the output file.
-//
-// emit is a wrapper around writing a formatted string to the output
-// buffer. emit can be invoked in one of two ways:
-//
-// (1) emit("some string")
-// When emit is called with a single string argument, it is simply copied to
-// the output buffer without any further formatting.
-// (2) emit(fmtString, args...)
-// emit can also be invoked in a similar fashion to *Printf() functions,
-// where the first argument is a format string.
-//
-// Calling emit with a single argument that is not a string will result in a
-// panic, as the caller's intent is ambiguous.
-func emit(out io.Writer, indent int, a ...interface{}) {
- const spacesPerIndentLevel = 4
-
- if len(a) < 1 {
- panic("emit() called with no arguments")
- }
-
- if indent > 0 {
- if _, err := fmt.Fprint(out, strings.Repeat(" ", indent*spacesPerIndentLevel)); err != nil {
- // Writing to the emit output should not fail. Typically the output
- // is a byte.Buffer; writes to these never fail.
- panic(err)
- }
- }
-
- first, ok := a[0].(string)
- if !ok {
- // First argument must be either the string to emit (case 1 from
- // function-level comment), or a format string (case 2).
- panic(fmt.Sprintf("First argument to emit() is not a string: %+v", a[0]))
- }
-
- if len(a) == 1 {
- // Single string argument. Assume no formatting requested.
- if _, err := fmt.Fprint(out, first); err != nil {
- // Writing to out should not fail.
- panic(err)
- }
- return
-
- }
-
- // Formatting requested.
- if _, err := fmt.Fprintf(out, first, a[1:]...); err != nil {
- // Writing to out should not fail.
- panic(err)
- }
-}
-
-// sourceBuffer represents fragments of generated go source code.
-//
-// sourceBuffer provides a convenient way to build up go souce fragments in
-// memory. May be safely zero-value initialized. Not thread-safe.
-type sourceBuffer struct {
- // Current indentation level.
- indent int
-
- // Memory buffer containing contents while they're being generated.
- b bytes.Buffer
-}
-
-func (b *sourceBuffer) incIndent() {
- b.indent++
-}
-
-func (b *sourceBuffer) decIndent() {
- if b.indent <= 0 {
- panic("decIndent() without matching incIndent()")
- }
- b.indent--
-}
-
-func (b *sourceBuffer) emit(a ...interface{}) {
- emit(&b.b, b.indent, a...)
-}
-
-func (b *sourceBuffer) emitNoIndent(a ...interface{}) {
- emit(&b.b, 0 /*indent*/, a...)
-}
-
-func (b *sourceBuffer) inIndent(body func()) {
- b.incIndent()
- body()
- b.decIndent()
-}
-
-func (b *sourceBuffer) write(out io.Writer) error {
- _, err := fmt.Fprint(out, b.b.String())
- return err
-}
-
-// Write implements io.Writer.Write.
-func (b *sourceBuffer) Write(buf []byte) (int, error) {
- return (b.b.Write(buf))
-}
-
-// importStmt represents a single import statement.
-type importStmt struct {
- // Local name of the imported package.
- name string
- // Import path.
- path string
- // Indicates whether the local name is an alias, or simply the final
- // component of the path.
- aliased bool
- // Indicates whether this import was referenced by generated code.
- used bool
-}
-
-func newImport(p string) *importStmt {
- name := path.Base(p)
- return &importStmt{
- name: name,
- path: p,
- aliased: false,
- }
-}
-
-func newImportFromSpec(spec *ast.ImportSpec, f *token.FileSet) *importStmt {
- p := spec.Path.Value[1 : len(spec.Path.Value)-1] // Strip the " quotes around path.
- name := path.Base(p)
- if name == "" || name == "/" || name == "." {
- panic(fmt.Sprintf("Couldn't process local package name for import at %s, (processed as %s)",
- f.Position(spec.Path.Pos()), name))
- }
- if spec.Name != nil {
- name = spec.Name.Name
- }
- return &importStmt{
- name: name,
- path: p,
- aliased: spec.Name != nil,
- }
-}
-
-func (i *importStmt) String() string {
- if i.aliased {
- return fmt.Sprintf("%s \"%s\"", i.name, i.path)
- }
- return fmt.Sprintf("\"%s\"", i.path)
-}
-
-func (i *importStmt) markUsed() {
- i.used = true
-}
-
-func (i *importStmt) equivalent(other *importStmt) bool {
- return i == other
-}
-
-// importTable represents a collection of importStmts.
-type importTable struct {
- // Map of imports and whether they should be copied to the output.
- is map[string]*importStmt
-}
-
-func newImportTable() *importTable {
- return &importTable{
- is: make(map[string]*importStmt),
- }
-}
-
-// Merges import statements from other into i. Collisions in import statements
-// result in a panic.
-func (i *importTable) merge(other *importTable) {
- for name, im := range other.is {
- if dup, ok := i.is[name]; ok && dup.equivalent(im) {
- panic(fmt.Sprintf("Found colliding import statements: ours: %+v, other's: %+v", dup, im))
- }
-
- i.is[name] = im
- }
-}
-
-func (i *importTable) add(s string) *importStmt {
- n := newImport(s)
- i.is[n.name] = n
- return n
-}
-
-func (i *importTable) addFromSpec(spec *ast.ImportSpec, f *token.FileSet) *importStmt {
- n := newImportFromSpec(spec, f)
- i.is[n.name] = n
- return n
-}
-
-// Marks the import named n as used. If no such import is in the table, returns
-// false.
-func (i *importTable) markUsed(n string) bool {
- if n, ok := i.is[n]; ok {
- n.markUsed()
- return true
- }
- return false
-}
-
-func (i *importTable) clear() {
- for _, i := range i.is {
- i.used = false
- }
-}
-
-func (i *importTable) write(out io.Writer) error {
- if len(i.is) == 0 {
- // Nothing to import, we're done.
- return nil
- }
-
- imports := make([]string, 0, len(i.is))
- for _, i := range i.is {
- if i.used {
- imports = append(imports, i.String())
- }
- }
- sort.Strings(imports)
-
- var b sourceBuffer
- b.emit("import (\n")
- b.incIndent()
- for _, i := range imports {
- b.emit("%s\n", i)
- }
- b.decIndent()
- b.emit(")\n\n")
-
- return b.write(out)
-}
diff --git a/tools/go_marshal/main.go b/tools/go_marshal/main.go
deleted file mode 100644
index 3d12eb93c..000000000
--- a/tools/go_marshal/main.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2019 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// go_marshal is a code generation utility for automatically generating code to
-// marshal go data structures to memory.
-//
-// This binary is typically run as part of the build process, and is invoked by
-// the go_marshal bazel rule defined in defs.bzl.
-//
-// See README.md.
-package main
-
-import (
- "flag"
- "fmt"
- "os"
- "strings"
-
- "gvisor.dev/gvisor/tools/go_marshal/gomarshal"
-)
-
-var (
- pkg = flag.String("pkg", "", "output package")
- output = flag.String("output", "", "output file")
- outputTest = flag.String("output_test", "", "output file for tests")
- imports = flag.String("imports", "", "comma-separated list of extra packages to import in generated code")
- declarationPkg = flag.String("declarationPkg", "", "import path of target declaring the types we're generating on")
-)
-
-func main() {
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, "Usage: %s <input go src files>\n", os.Args[0])
- flag.PrintDefaults()
- }
- flag.Parse()
- if len(flag.Args()) == 0 {
- flag.Usage()
- os.Exit(1)
- }
-
- if *pkg == "" {
- flag.Usage()
- fmt.Fprint(os.Stderr, "Flag -pkg must be provided.\n")
- os.Exit(1)
- }
-
- var extraImports []string
- if len(*imports) > 0 {
- // Note: strings.Split(s, sep) returns s if sep doesn't exist in s. Thus
- // we check for an empty imports list to avoid emitting an empty string
- // as an import.
- extraImports = strings.Split(*imports, ",")
- }
- g, err := gomarshal.NewGenerator(flag.Args(), *output, *outputTest, *pkg, *declarationPkg, extraImports)
- if err != nil {
- panic(err)
- }
-
- if err := g.Run(); err != nil {
- panic(err)
- }
-}
diff --git a/tools/go_marshal/marshal/BUILD b/tools/go_marshal/marshal/BUILD
deleted file mode 100644
index 47dda97a1..000000000
--- a/tools/go_marshal/marshal/BUILD
+++ /dev/null
@@ -1,14 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_library")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "marshal",
- srcs = [
- "marshal.go",
- ],
- importpath = "gvisor.dev/gvisor/tools/go_marshal/marshal",
- visibility = [
- "//:sandbox",
- ],
-)
diff --git a/tools/go_marshal/marshal/marshal.go b/tools/go_marshal/marshal/marshal.go
deleted file mode 100644
index a313a27ed..000000000
--- a/tools/go_marshal/marshal/marshal.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package marshal defines the Marshallable interface for
-// serialize/deserializing go data structures to/from memory, according to the
-// Linux ABI.
-//
-// Implementations of this interface are typically automatically generated by
-// tools/go_marshal. See the go_marshal README for details.
-package marshal
-
-// Marshallable represents a type that can be marshalled to and from memory.
-type Marshallable interface {
- // SizeBytes is the size of the memory representation of a type in
- // marshalled form.
- SizeBytes() int
-
- // MarshalBytes serializes a copy of a type to dst. dst must be at least
- // SizeBytes() long.
- MarshalBytes(dst []byte)
-
- // UnmarshalBytes deserializes a type from src. src must be at least
- // SizeBytes() long.
- UnmarshalBytes(src []byte)
-
- // Packed returns true if the marshalled size of the type is the same as the
- // size it occupies in memory. This happens when the type has no fields
- // starting at unaligned addresses (should always be true by default for ABI
- // structs, verified by automatically generated tests when using
- // go_marshal), and has no fields marked `marshal:"unaligned"`.
- Packed() bool
-
- // MarshalUnsafe serializes a type by bulk copying its in-memory
- // representation to the dst buffer. This is only safe to do when the type
- // has no implicit padding, see Marshallable.Packed. When Packed would
- // return false, MarshalUnsafe should fall back to the safer but slower
- // MarshalBytes.
- MarshalUnsafe(dst []byte)
-
- // UnmarshalUnsafe deserializes a type directly to the underlying memory
- // allocated for the object by the runtime.
- //
- // This allows much faster unmarshalling of types which have no implicit
- // padding, see Marshallable.Packed. When Packed would return false,
- // UnmarshalUnsafe should fall back to the safer but slower unmarshal
- // mechanism implemented in UnmarshalBytes (usually by calling
- // UnmarshalBytes directly).
- UnmarshalUnsafe(src []byte)
-}
diff --git a/tools/go_marshal/test/BUILD b/tools/go_marshal/test/BUILD
deleted file mode 100644
index d412e1ccf..000000000
--- a/tools/go_marshal/test/BUILD
+++ /dev/null
@@ -1,30 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_test")
-load("//tools/go_marshal:defs.bzl", "go_library")
-
-package(licenses = ["notice"])
-
-package_group(
- name = "gomarshal_test",
- packages = [
- "//tools/go_marshal/test/...",
- ],
-)
-
-go_test(
- name = "benchmark_test",
- srcs = ["benchmark_test.go"],
- deps = [
- ":test",
- "//pkg/binary",
- "//pkg/sentry/usermem",
- "//tools/go_marshal/analysis",
- ],
-)
-
-go_library(
- name = "test",
- testonly = 1,
- srcs = ["test.go"],
- importpath = "gvisor.dev/gvisor/tools/go_marshal/test",
- deps = ["//tools/go_marshal/test/external"],
-)
diff --git a/tools/go_marshal/test/benchmark_test.go b/tools/go_marshal/test/benchmark_test.go
deleted file mode 100644
index e70db06d8..000000000
--- a/tools/go_marshal/test/benchmark_test.go
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package benchmark_test
-
-import (
- "bytes"
- encbin "encoding/binary"
- "fmt"
- "reflect"
- "testing"
-
- "gvisor.dev/gvisor/pkg/binary"
- "gvisor.dev/gvisor/pkg/sentry/usermem"
- "gvisor.dev/gvisor/tools/go_marshal/analysis"
- test "gvisor.dev/gvisor/tools/go_marshal/test"
-)
-
-// Marshalling using the standard encoding/binary package.
-func BenchmarkEncodingBinary(b *testing.B) {
- var s1, s2 test.Stat
- analysis.RandomizeValue(&s1)
-
- size := encbin.Size(&s1)
-
- b.ResetTimer()
-
- for n := 0; n < b.N; n++ {
- buf := bytes.NewBuffer(make([]byte, size))
- buf.Reset()
- if err := encbin.Write(buf, usermem.ByteOrder, &s1); err != nil {
- b.Error("Write:", err)
- }
- if err := encbin.Read(buf, usermem.ByteOrder, &s2); err != nil {
- b.Error("Read:", err)
- }
- }
-
- b.StopTimer()
-
- // Sanity check, make sure the values were preserved.
- if !reflect.DeepEqual(s1, s2) {
- panic(fmt.Sprintf("Data corruption across marshal/unmarshal cycle:\nBefore: %+v\nAfter: %+v\n", s1, s2))
- }
-}
-
-// Marshalling using the sentry's binary.Marshal.
-func BenchmarkBinary(b *testing.B) {
- var s1, s2 test.Stat
- analysis.RandomizeValue(&s1)
-
- size := binary.Size(s1)
-
- b.ResetTimer()
-
- for n := 0; n < b.N; n++ {
- buf := make([]byte, 0, size)
- buf = binary.Marshal(buf, usermem.ByteOrder, &s1)
- binary.Unmarshal(buf, usermem.ByteOrder, &s2)
- }
-
- b.StopTimer()
-
- // Sanity check, make sure the values were preserved.
- if !reflect.DeepEqual(s1, s2) {
- panic(fmt.Sprintf("Data corruption across marshal/unmarshal cycle:\nBefore: %+v\nAfter: %+v\n", s1, s2))
- }
-}
-
-// Marshalling field-by-field with manually-written code.
-func BenchmarkMarshalManual(b *testing.B) {
- var s1, s2 test.Stat
- analysis.RandomizeValue(&s1)
-
- b.ResetTimer()
-
- for n := 0; n < b.N; n++ {
- buf := make([]byte, 0, s1.SizeBytes())
-
- // Marshal
- buf = binary.AppendUint64(buf, usermem.ByteOrder, s1.Dev)
- buf = binary.AppendUint64(buf, usermem.ByteOrder, s1.Ino)
- buf = binary.AppendUint64(buf, usermem.ByteOrder, s1.Nlink)
- buf = binary.AppendUint32(buf, usermem.ByteOrder, s1.Mode)
- buf = binary.AppendUint32(buf, usermem.ByteOrder, s1.UID)
- buf = binary.AppendUint32(buf, usermem.ByteOrder, s1.GID)
- buf = binary.AppendUint32(buf, usermem.ByteOrder, 0)
- buf = binary.AppendUint64(buf, usermem.ByteOrder, s1.Rdev)
- buf = binary.AppendUint64(buf, usermem.ByteOrder, uint64(s1.Size))
- buf = binary.AppendUint64(buf, usermem.ByteOrder, uint64(s1.Blksize))
- buf = binary.AppendUint64(buf, usermem.ByteOrder, uint64(s1.Blocks))
- buf = binary.AppendUint64(buf, usermem.ByteOrder, uint64(s1.ATime.Sec))
- buf = binary.AppendUint64(buf, usermem.ByteOrder, uint64(s1.ATime.Nsec))
- buf = binary.AppendUint64(buf, usermem.ByteOrder, uint64(s1.MTime.Sec))
- buf = binary.AppendUint64(buf, usermem.ByteOrder, uint64(s1.MTime.Nsec))
- buf = binary.AppendUint64(buf, usermem.ByteOrder, uint64(s1.CTime.Sec))
- buf = binary.AppendUint64(buf, usermem.ByteOrder, uint64(s1.CTime.Nsec))
-
- // Unmarshal
- s2.Dev = usermem.ByteOrder.Uint64(buf[0:8])
- s2.Ino = usermem.ByteOrder.Uint64(buf[8:16])
- s2.Nlink = usermem.ByteOrder.Uint64(buf[16:24])
- s2.Mode = usermem.ByteOrder.Uint32(buf[24:28])
- s2.UID = usermem.ByteOrder.Uint32(buf[28:32])
- s2.GID = usermem.ByteOrder.Uint32(buf[32:36])
- // Padding: buf[36:40]
- s2.Rdev = usermem.ByteOrder.Uint64(buf[40:48])
- s2.Size = int64(usermem.ByteOrder.Uint64(buf[48:56]))
- s2.Blksize = int64(usermem.ByteOrder.Uint64(buf[56:64]))
- s2.Blocks = int64(usermem.ByteOrder.Uint64(buf[64:72]))
- s2.ATime.Sec = int64(usermem.ByteOrder.Uint64(buf[72:80]))
- s2.ATime.Nsec = int64(usermem.ByteOrder.Uint64(buf[80:88]))
- s2.MTime.Sec = int64(usermem.ByteOrder.Uint64(buf[88:96]))
- s2.MTime.Nsec = int64(usermem.ByteOrder.Uint64(buf[96:104]))
- s2.CTime.Sec = int64(usermem.ByteOrder.Uint64(buf[104:112]))
- s2.CTime.Nsec = int64(usermem.ByteOrder.Uint64(buf[112:120]))
- }
-
- b.StopTimer()
-
- // Sanity check, make sure the values were preserved.
- if !reflect.DeepEqual(s1, s2) {
- panic(fmt.Sprintf("Data corruption across marshal/unmarshal cycle:\nBefore: %+v\nAfter: %+v\n", s1, s2))
- }
-}
-
-// Marshalling with the go_marshal safe API.
-func BenchmarkGoMarshalSafe(b *testing.B) {
- var s1, s2 test.Stat
- analysis.RandomizeValue(&s1)
-
- b.ResetTimer()
-
- for n := 0; n < b.N; n++ {
- buf := make([]byte, s1.SizeBytes())
- s1.MarshalBytes(buf)
- s2.UnmarshalBytes(buf)
- }
-
- b.StopTimer()
-
- // Sanity check, make sure the values were preserved.
- if !reflect.DeepEqual(s1, s2) {
- panic(fmt.Sprintf("Data corruption across marshal/unmarshal cycle:\nBefore: %+v\nAfter: %+v\n", s1, s2))
- }
-}
-
-// Marshalling with the go_marshal unsafe API.
-func BenchmarkGoMarshalUnsafe(b *testing.B) {
- var s1, s2 test.Stat
- analysis.RandomizeValue(&s1)
-
- b.ResetTimer()
-
- for n := 0; n < b.N; n++ {
- buf := make([]byte, s1.SizeBytes())
- s1.MarshalUnsafe(buf)
- s2.UnmarshalUnsafe(buf)
- }
-
- b.StopTimer()
-
- // Sanity check, make sure the values were preserved.
- if !reflect.DeepEqual(s1, s2) {
- panic(fmt.Sprintf("Data corruption across marshal/unmarshal cycle:\nBefore: %+v\nAfter: %+v\n", s1, s2))
- }
-}
diff --git a/tools/go_marshal/test/external/BUILD b/tools/go_marshal/test/external/BUILD
deleted file mode 100644
index 9bb89e1da..000000000
--- a/tools/go_marshal/test/external/BUILD
+++ /dev/null
@@ -1,11 +0,0 @@
-load("//tools/go_marshal:defs.bzl", "go_library")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "external",
- testonly = 1,
- srcs = ["external.go"],
- importpath = "gvisor.dev/gvisor/tools/go_marshal/test/external",
- visibility = ["//tools/go_marshal/test:gomarshal_test"],
-)
diff --git a/tools/go_marshal/test/external/external.go b/tools/go_marshal/test/external/external.go
deleted file mode 100644
index 4be3722f3..000000000
--- a/tools/go_marshal/test/external/external.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package external defines types we can import for testing.
-package external
-
-// External is a public Marshallable type for use in testing.
-//
-// +marshal
-type External struct {
- j int64
-}
diff --git a/tools/go_marshal/test/test.go b/tools/go_marshal/test/test.go
deleted file mode 100644
index 8de02d707..000000000
--- a/tools/go_marshal/test/test.go
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package test contains data structures for testing the go_marshal tool.
-package test
-
-import (
- // We're intentionally using a package name alias here even though it's not
- // necessary to test the code generator's ability to handle package aliases.
- ex "gvisor.dev/gvisor/tools/go_marshal/test/external"
-)
-
-// Type1 is a test data type.
-//
-// +marshal
-type Type1 struct {
- a Type2
- x, y int64 // Multiple field names.
- b byte `marshal:"unaligned"` // Short field.
- c uint64
- _ uint32 // Unnamed scalar field.
- _ [6]byte // Unnamed vector field, typical padding.
- _ [2]byte
- xs [8]int32
- as [10]Type2 `marshal:"unaligned"` // Array of Marshallable objects.
- ss Type3
-}
-
-// Type2 is a test data type.
-//
-// +marshal
-type Type2 struct {
- n int64
- c byte
- _ [7]byte
- m int64
- a int64
-}
-
-// Type3 is a test data type.
-//
-// +marshal
-type Type3 struct {
- s int64
- x ex.External // Type defined in another package.
-}
-
-// Type4 is a test data type.
-//
-// +marshal
-type Type4 struct {
- c byte
- x int64 `marshal:"unaligned"`
- d byte
- _ [7]byte
-}
-
-// Type5 is a test data type.
-//
-// +marshal
-type Type5 struct {
- n int64
- t Type4
- m int64
-}
-
-// Timespec represents struct timespec in <time.h>.
-//
-// +marshal
-type Timespec struct {
- Sec int64
- Nsec int64
-}
-
-// Stat represents struct stat.
-//
-// +marshal
-type Stat struct {
- Dev uint64
- Ino uint64
- Nlink uint64
- Mode uint32
- UID uint32
- GID uint32
- _ int32
- Rdev uint64
- Size int64
- Blksize int64
- Blocks int64
- ATime Timespec
- MTime Timespec
- CTime Timespec
- _ [3]int64
-}
diff --git a/tools/go_stateify/BUILD b/tools/go_stateify/BUILD
deleted file mode 100644
index bb53f8ae9..000000000
--- a/tools/go_stateify/BUILD
+++ /dev/null
@@ -1,9 +0,0 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary")
-
-package(licenses = ["notice"])
-
-go_binary(
- name = "stateify",
- srcs = ["main.go"],
- visibility = ["//visibility:public"],
-)
diff --git a/tools/go_stateify/defs.bzl b/tools/go_stateify/defs.bzl
deleted file mode 100644
index 3ce36c1c8..000000000
--- a/tools/go_stateify/defs.bzl
+++ /dev/null
@@ -1,136 +0,0 @@
-"""Stateify is a tool for generating state wrappers for Go types.
-
-The recommended way is to use the go_library rule defined below with mostly
-identical configuration as the native go_library rule.
-
-load("//tools/go_stateify:defs.bzl", "go_library")
-
-go_library(
- name = "foo",
- srcs = ["foo.go"],
-)
-
-Under the hood, the go_stateify rule is used to generate a file that will
-appear in a Go target; the output file should appear explicitly in a srcs list.
-For example (the above is still the preferred way):
-
-load("//tools/go_stateify:defs.bzl", "go_stateify")
-
-go_stateify(
- name = "foo_state",
- srcs = ["foo.go"],
- out = "foo_state.go",
- package = "foo",
-)
-
-go_library(
- name = "foo",
- srcs = [
- "foo.go",
- "foo_state.go",
- ],
- deps = [
- "//pkg/state",
- ],
-)
-"""
-
-load("@io_bazel_rules_go//go:def.bzl", _go_library = "go_library")
-
-def _go_stateify_impl(ctx):
- """Implementation for the stateify tool."""
- output = ctx.outputs.out
-
- # Run the stateify command.
- args = ["-output=%s" % output.path]
- args += ["-pkg=%s" % ctx.attr.package]
- if ctx.attr._statepkg:
- args += ["-statepkg=%s" % ctx.attr._statepkg]
- if ctx.attr.imports:
- args += ["-imports=%s" % ",".join(ctx.attr.imports)]
- args += ["--"]
- for src in ctx.attr.srcs:
- args += [f.path for f in src.files.to_list()]
- ctx.actions.run(
- inputs = ctx.files.srcs,
- outputs = [output],
- mnemonic = "GoStateify",
- progress_message = "Generating state library %s" % ctx.label,
- arguments = args,
- executable = ctx.executable._tool,
- )
-
-go_stateify = rule(
- implementation = _go_stateify_impl,
- doc = "Generates save and restore logic from a set of Go files.",
- attrs = {
- "srcs": attr.label_list(
- doc = """
-The input source files. These files should include all structs in the package
-that need to be saved.
-""",
- mandatory = True,
- allow_files = True,
- ),
- "imports": attr.string_list(
- doc = """
-An optional list of extra non-aliased, Go-style absolute import paths required
-for statified types.
-""",
- mandatory = False,
- ),
- "package": attr.string(
- doc = "The package name for the input sources.",
- mandatory = True,
- ),
- "out": attr.output(
- doc = """
-The name of the generated file output. This must not conflict with any other
-files and must be added to the srcs of the relevant go_library.
-""",
- mandatory = True,
- ),
- "_tool": attr.label(
- executable = True,
- cfg = "host",
- default = Label("//tools/go_stateify:stateify"),
- ),
- "_statepkg": attr.string(default = "gvisor.dev/gvisor/pkg/state"),
- },
-)
-
-def go_library(name, srcs, deps = [], imports = [], **kwargs):
- """Standard go_library wrapped which generates state source files.
-
- Args:
- name: the name of the go_library rule.
- srcs: sources of the go_library. Each will be processed for stateify
- annotations.
- deps: dependencies for the go_library.
- imports: an optional list of extra non-aliased, Go-style absolute import
- paths required for stateified types.
- **kwargs: passed to go_library.
- """
- if "encode_unsafe.go" not in srcs and (name + "_state_autogen.go") not in srcs:
- # Only do stateification for non-state packages without manual autogen.
- go_stateify(
- name = name + "_state_autogen",
- srcs = [src for src in srcs if src.endswith(".go")],
- imports = imports,
- package = name,
- out = name + "_state_autogen.go",
- )
- all_srcs = srcs + [name + "_state_autogen.go"]
- if "//pkg/state" not in deps:
- all_deps = deps + ["//pkg/state"]
- else:
- all_deps = deps
- else:
- all_deps = deps
- all_srcs = srcs
- _go_library(
- name = name,
- srcs = all_srcs,
- deps = all_deps,
- **kwargs
- )
diff --git a/tools/go_stateify/main.go b/tools/go_stateify/main.go
deleted file mode 100644
index db7a7107b..000000000
--- a/tools/go_stateify/main.go
+++ /dev/null
@@ -1,418 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Stateify provides a simple way to generate Load/Save methods based on
-// existing types and struct tags.
-package main
-
-import (
- "flag"
- "fmt"
- "go/ast"
- "go/parser"
- "go/token"
- "os"
- "reflect"
- "strings"
- "sync"
-)
-
-var (
- pkg = flag.String("pkg", "", "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")
-)
-
-// resolveTypeName returns a qualified type name.
-func resolveTypeName(name string, typ ast.Expr) (field string, qualified string) {
- for done := false; !done; {
- // Resolve star expressions.
- switch rs := typ.(type) {
- case *ast.StarExpr:
- qualified += "*"
- typ = rs.X
- case *ast.ArrayType:
- if rs.Len == nil {
- // Slice type declaration.
- qualified += "[]"
- } else {
- // Array type declaration.
- qualified += "[" + rs.Len.(*ast.BasicLit).Value + "]"
- }
- typ = rs.Elt
- default:
- // No more descent.
- done = true
- }
- }
-
- // Resolve a package selector.
- sel, ok := typ.(*ast.SelectorExpr)
- if ok {
- qualified = qualified + sel.X.(*ast.Ident).Name + "."
- typ = sel.Sel
- }
-
- // Figure out actual type name.
- ident, ok := typ.(*ast.Ident)
- if !ok {
- panic(fmt.Sprintf("type not supported: %s (involves anonymous types?)", name))
- }
- field = ident.Name
- qualified = qualified + field
- return
-}
-
-// extractStateTag pulls the relevant state tag.
-func extractStateTag(tag *ast.BasicLit) string {
- if tag == nil {
- return ""
- }
- if len(tag.Value) < 2 {
- return ""
- }
- return reflect.StructTag(tag.Value[1 : len(tag.Value)-1]).Get("state")
-}
-
-// scanFunctions is a set of functions passed to scanFields.
-type scanFunctions struct {
- zerovalue func(name string)
- normal func(name string)
- wait func(name string)
- value func(name, typName string)
-}
-
-// scanFields scans the fields of a struct.
-//
-// Each provided function will be applied to appropriately tagged fields, or
-// skipped if nil.
-//
-// Fields tagged nosave are skipped.
-func scanFields(ss *ast.StructType, fn scanFunctions) {
- if ss.Fields.List == nil {
- // No fields.
- return
- }
-
- // Scan all fields.
- for _, field := range ss.Fields.List {
- // Calculate the name.
- name := ""
- if field.Names != nil {
- // It's a named field; override.
- name = field.Names[0].Name
- } else {
- // Anonymous types can't be embedded, so we don't need
- // to worry about providing a useful name here.
- name, _ = resolveTypeName("", field.Type)
- }
-
- // Skip _ fields.
- if name == "_" {
- continue
- }
-
- switch tag := extractStateTag(field.Tag); tag {
- case "zerovalue":
- if fn.zerovalue != nil {
- fn.zerovalue(name)
- }
-
- case "":
- if fn.normal != nil {
- fn.normal(name)
- }
-
- case "wait":
- if fn.wait != nil {
- fn.wait(name)
- }
-
- case "manual", "nosave", "ignore":
- // Do nothing.
-
- default:
- if strings.HasPrefix(tag, ".(") && strings.HasSuffix(tag, ")") {
- if fn.value != nil {
- fn.value(name, tag[2:len(tag)-1])
- }
- }
- }
- }
-}
-
-func camelCased(name string) string {
- return strings.ToUpper(name[:1]) + name[1:]
-}
-
-func main() {
- // Parse flags.
- flag.Usage = func() {
- fmt.Fprintf(os.Stderr, "Usage: %s [options]\n", os.Args[0])
- flag.PrintDefaults()
- }
- flag.Parse()
- if len(flag.Args()) == 0 {
- flag.Usage()
- os.Exit(1)
- }
- if *pkg == "" {
- fmt.Fprintf(os.Stderr, "Error: package required.")
- os.Exit(1)
- }
-
- // Open the output file.
- var (
- outputFile *os.File
- err error
- )
- if *output == "" || *output == "-" {
- outputFile = os.Stdout
- } else {
- outputFile, err = os.OpenFile(*output, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
- if err != nil {
- fmt.Fprintf(os.Stderr, "Error opening output %q: %v", *output, err)
- }
- defer outputFile.Close()
- }
-
- // Set the statePrefix for below, depending on the import.
- statePrefix := ""
- if *statePkg != "" {
- parts := strings.Split(*statePkg, "/")
- statePrefix = parts[len(parts)-1] + "."
- }
-
- // initCalls is dumped at the end.
- var initCalls []string
-
- // 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))
- }
- 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)
- }
- emitLoadValue := func(name, typName string) {
- fmt.Fprintf(outputFile, " m.LoadValue(\"%s\", new(%s), func(y interface{}) { x.load%s(y.(%s)) })\n", name, typName, camelCased(name), typName)
- }
- emitLoad := func(name string) {
- fmt.Fprintf(outputFile, " m.Load(\"%s\", &x.%s)\n", name, name)
- }
- emitLoadWait := func(name string) {
- fmt.Fprintf(outputFile, " m.LoadWait(\"%s\", &x.%s)\n", name, name)
- }
- emitSaveValue := func(name, typName string) {
- fmt.Fprintf(outputFile, " var %s %s = x.save%s()\n", name, typName, camelCased(name))
- fmt.Fprintf(outputFile, " m.SaveValue(\"%s\", %s)\n", name, name)
- }
- emitSave := func(name string) {
- fmt.Fprintf(outputFile, " m.Save(\"%s\", &x.%s)\n", name, name)
- }
-
- // Emit the package name.
- fmt.Fprint(outputFile, "// automatically generated by stateify.\n\n")
- fmt.Fprintf(outputFile, "package %s\n\n", *pkg)
-
- // Emit the imports lazily.
- var once sync.Once
- maybeEmitImports := func() {
- once.Do(func() {
- // Emit the imports.
- fmt.Fprint(outputFile, "import (\n")
- if *statePkg != "" {
- fmt.Fprintf(outputFile, " \"%s\"\n", *statePkg)
- }
- if *imports != "" {
- for _, i := range strings.Split(*imports, ",") {
- fmt.Fprintf(outputFile, " \"%s\"\n", i)
- }
- }
- fmt.Fprint(outputFile, ")\n\n")
- })
- }
-
- files := make([]*ast.File, 0, len(flag.Args()))
-
- // Parse the input files.
- for _, filename := range flag.Args() {
- // Parse the file.
- fset := token.NewFileSet()
- f, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)
- if err != nil {
- // Not a valid input file?
- fmt.Fprintf(os.Stderr, "Input %q can't be parsed: %v\n", filename, err)
- os.Exit(1)
- }
- files = append(files, f)
- }
-
- type method struct {
- receiver string
- name string
- }
-
- // Search for and add all methods with a pointer receiver and no other
- // arguments to a set. We support auto-detecting the existence of
- // several different methods with this signature.
- simpleMethods := map[method]struct{}{}
- for _, f := range files {
-
- // Go over all functions.
- for _, decl := range f.Decls {
- d, ok := decl.(*ast.FuncDecl)
- if !ok {
- continue
- }
- if d.Name == nil || d.Recv == nil || d.Type == nil {
- // Not a named method.
- continue
- }
- if len(d.Recv.List) != 1 {
- // Wrong number of receivers?
- continue
- }
- if d.Type.Params != nil && len(d.Type.Params.List) != 0 {
- // Has argument(s).
- continue
- }
- if d.Type.Results != nil && len(d.Type.Results.List) != 0 {
- // Has return(s).
- continue
- }
-
- pt, ok := d.Recv.List[0].Type.(*ast.StarExpr)
- if !ok {
- // Not a pointer receiver.
- continue
- }
-
- t, ok := pt.X.(*ast.Ident)
- if !ok {
- // This shouldn't happen with valid Go.
- continue
- }
-
- simpleMethods[method{t.Name, d.Name.Name}] = struct{}{}
- }
- }
-
- for _, f := range files {
- // Go over all named types.
- for _, decl := range f.Decls {
- d, ok := decl.(*ast.GenDecl)
- if !ok || d.Tok != token.TYPE {
- continue
- }
-
- // Only generate code for types marked
- // "// +stateify savable" in one of the proceeding
- // comment lines.
- if d.Doc == nil {
- continue
- }
- savable := false
- for _, l := range d.Doc.List {
- if l.Text == "// +stateify savable" {
- savable = true
- break
- }
- }
- if !savable {
- continue
- }
-
- for _, gs := range d.Specs {
- ts := gs.(*ast.TypeSpec)
- switch ts.Type.(type) {
- case *ast.InterfaceType, *ast.ChanType, *ast.FuncType, *ast.ParenExpr, *ast.StarExpr:
- // Don't register.
- break
- case *ast.StructType:
- maybeEmitImports()
-
- ss := ts.Type.(*ast.StructType)
-
- // Define beforeSave if a definition was not found. This
- // prevents the code from compiling if a custom beforeSave
- // was defined in a file not provided to this binary and
- // prevents inherited methods from being called multiple times
- // by overriding them.
- if _, ok := simpleMethods[method{ts.Name.Name, "beforeSave"}]; !ok {
- fmt.Fprintf(outputFile, "func (x *%s) beforeSave() {}\n", ts.Name.Name)
- }
-
- // Generate the save method.
- fmt.Fprintf(outputFile, "func (x *%s) save(m %sMap) {\n", ts.Name.Name, statePrefix)
- fmt.Fprintf(outputFile, " x.beforeSave()\n")
- scanFields(ss, scanFunctions{zerovalue: emitZeroCheck})
- scanFields(ss, scanFunctions{value: emitSaveValue})
- scanFields(ss, scanFunctions{normal: emitSave, wait: emitSave})
- fmt.Fprintf(outputFile, "}\n\n")
-
- // Define afterLoad if a definition was not found. We do this
- // for the same reason that we do it for beforeSave.
- _, hasAfterLoad := simpleMethods[method{ts.Name.Name, "afterLoad"}]
- if !hasAfterLoad {
- fmt.Fprintf(outputFile, "func (x *%s) afterLoad() {}\n", ts.Name.Name)
- }
-
- // Generate the load method.
- //
- // Note that the manual loads always follow the
- // automated loads.
- fmt.Fprintf(outputFile, "func (x *%s) load(m %sMap) {\n", ts.Name.Name, statePrefix)
- scanFields(ss, scanFunctions{normal: emitLoad, wait: emitLoadWait})
- scanFields(ss, scanFunctions{value: emitLoadValue})
- if hasAfterLoad {
- // The call to afterLoad is made conditionally, because when
- // AfterLoad is called, the object encodes a dependency on
- // referred objects (i.e. fields). This means that afterLoad
- // will not be called until the other afterLoads are called.
- fmt.Fprintf(outputFile, " m.AfterLoad(x.afterLoad)\n")
- }
- fmt.Fprintf(outputFile, "}\n\n")
-
- // Add to our registration.
- emitRegister(ts.Name.Name)
- case *ast.Ident, *ast.SelectorExpr, *ast.ArrayType:
- maybeEmitImports()
-
- _, val := resolveTypeName(ts.Name.Name, ts.Type)
-
- // Dispatch directly.
- fmt.Fprintf(outputFile, "func (x *%s) save(m %sMap) {\n", ts.Name.Name, statePrefix)
- fmt.Fprintf(outputFile, " m.SaveValue(\"\", (%s)(*x))\n", val)
- fmt.Fprintf(outputFile, "}\n\n")
- fmt.Fprintf(outputFile, "func (x *%s) load(m %sMap) {\n", ts.Name.Name, statePrefix)
- fmt.Fprintf(outputFile, " m.LoadValue(\"\", new(%s), func(y interface{}) { *x = (%s)(y.(%s)) })\n", val, ts.Name.Name, val)
- fmt.Fprintf(outputFile, "}\n\n")
-
- // See above.
- emitRegister(ts.Name.Name)
- }
- }
- }
- }
-
- if len(initCalls) > 0 {
- // Emit the init() function.
- fmt.Fprintf(outputFile, "func init() {\n")
- for _, ic := range initCalls {
- fmt.Fprintf(outputFile, " %s\n", ic)
- }
- fmt.Fprintf(outputFile, "}\n")
- }
-}
diff --git a/tools/image_build.sh b/tools/image_build.sh
deleted file mode 100755
index 9b20a740d..000000000
--- a/tools/image_build.sh
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/bin/bash
-
-# Copyright 2019 The gVisor Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This script is responsible for building a new GCP image that: 1) has nested
-# virtualization enabled, and 2) has been completely set up with the
-# image_setup.sh script. This script should be idempotent, as we memoize the
-# setup script with a hash and check for that name.
-#
-# The GCP project name should be defined via a gcloud config.
-
-set -xeo pipefail
-
-# Parameters.
-declare -r ZONE=${ZONE:-us-central1-f}
-declare -r USERNAME=${USERNAME:-test}
-declare -r IMAGE_PROJECT=${IMAGE_PROJECT:-ubuntu-os-cloud}
-declare -r IMAGE_FAMILY=${IMAGE_FAMILY:-ubuntu-1604-lts}
-
-# Random names.
-declare -r DISK_NAME=$(mktemp -u disk-XXXXXX | tr A-Z a-z)
-declare -r SNAPSHOT_NAME=$(mktemp -u snapshot-XXXXXX | tr A-Z a-z)
-declare -r INSTANCE_NAME=$(mktemp -u build-XXXXXX | tr A-Z a-z)
-
-# Hashes inputs.
-declare -r SETUP_BLOB=$(echo ${ZONE} ${USERNAME} ${IMAGE_PROJECT} ${IMAGE_FAMILY} && sha256sum "$@")
-declare -r SETUP_HASH=$(echo ${SETUP_BLOB} | sha256sum - | cut -d' ' -f1 | cut -c 1-16)
-declare -r IMAGE_NAME=${IMAGE_NAME:-image-}${SETUP_HASH}
-
-# Does the image already exist? Skip the build.
-declare -r existing=$(gcloud compute images list --filter="name=(${IMAGE_NAME})" --format="value(name)")
-if ! [[ -z "${existing}" ]]; then
- echo "${existing}"
- exit 0
-fi
-
-# Set the zone for all actions.
-gcloud config set compute/zone "${ZONE}"
-
-# Start a unique instance. Note that this instance will have a unique persistent
-# disk as it's boot disk with the same name as the instance.
-gcloud compute instances create \
- --quiet \
- --image-project "${IMAGE_PROJECT}" \
- --image-family "${IMAGE_FAMILY}" \
- --boot-disk-size "200GB" \
- "${INSTANCE_NAME}"
-function cleanup {
- gcloud compute instances delete --quiet "${INSTANCE_NAME}"
-}
-trap cleanup EXIT
-
-# Wait for the instance to become available.
-declare attempts=0
-while [[ "${attempts}" -lt 30 ]]; do
- attempts=$((${attempts}+1))
- if gcloud compute ssh "${USERNAME}"@"${INSTANCE_NAME}" -- true; then
- break
- fi
-done
-if [[ "${attempts}" -ge 30 ]]; then
- echo "too many attempts: failed"
- exit 1
-fi
-
-# Run the install scripts provided.
-for arg; do
- gcloud compute ssh "${USERNAME}"@"${INSTANCE_NAME}" -- sudo bash - <"${arg}"
-done
-
-# Stop the instance; required before creating an image.
-gcloud compute instances stop --quiet "${INSTANCE_NAME}"
-
-# Create a snapshot of the instance disk.
-gcloud compute disks snapshot \
- --quiet \
- --zone="${ZONE}" \
- --snapshot-names="${SNAPSHOT_NAME}" \
- "${INSTANCE_NAME}"
-
-# Create the disk image.
-gcloud compute images create \
- --quiet \
- --source-snapshot="${SNAPSHOT_NAME}" \
- --licenses="https://www.googleapis.com/compute/v1/projects/vm-options/global/licenses/enable-vmx" \
- "${IMAGE_NAME}"
diff --git a/tools/make_repository.sh b/tools/make_repository.sh
deleted file mode 100755
index 27ffbc9f3..000000000
--- a/tools/make_repository.sh
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/bin/bash
-
-# Copyright 2018 The gVisor Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Parse arguments. We require more than two arguments, which are the private
-# keyring, the e-mail associated with the signer, and the list of packages.
-if [ "$#" -le 3 ]; then
- echo "usage: $0 <private-key> <signer-email> <component> <root> <packages...>"
- exit 1
-fi
-declare -r private_key=$(readlink -e "$1"); shift
-declare -r signer="$1"; shift
-declare -r component="$1"; shift
-declare -r root="$1"; shift
-
-# Verbose from this point.
-set -xeo pipefail
-
-# Create a temporary working directory. We don't remove this, as we ultimately
-# print this result and allow the caller to copy wherever they would like.
-declare -r tmpdir=$(mktemp -d /tmp/repoXXXXXX)
-
-# Create a temporary keyring, and ensure it is cleaned up.
-declare -r keyring=$(mktemp /tmp/keyringXXXXXX.gpg)
-cleanup() {
- rm -f "${keyring}"
-}
-trap cleanup EXIT
-gpg --no-default-keyring --keyring "${keyring}" --import "${private_key}" >&2
-
-# Copy the packages into the root.
-for pkg in "$@"; do
- name=$(basename "${pkg}" .deb)
- name=$(basename "${name}" .changes)
- arch=${name##*_}
- if [[ "${name}" == "${arch}" ]]; then
- continue # Not a regular package.
- fi
- if [[ "${pkg}" =~ ^.*\.deb$ ]]; then
- # Extract from the debian file.
- version=$(dpkg --info "${pkg}" | grep -E 'Version:' | cut -d':' -f2)
- elif [[ "${pkg}" =~ ^.*\.changes$ ]]; then
- # Extract from the changes file.
- version=$(grep -E 'Version:' "${pkg}" | cut -d':' -f2)
- else
- # Unsupported file type.
- echo "Unknown file type: ${pkg}"
- exit 1
- fi
- version=${version// /} # Trim whitespace.
- mkdir -p "${root}"/pool/"${version}"/binary-"${arch}"
- cp -a "${pkg}" "${root}"/pool/"${version}"/binary-"${arch}"
-done
-
-# Ensure all permissions are correct.
-find "${root}"/pool -type f -exec chmod 0644 {} \;
-
-# Sign all packages.
-for file in "${root}"/pool/*/binary-*/*.deb; do
- dpkg-sig -g "--no-default-keyring --keyring ${keyring}" --sign builder "${file}" >&2
-done
-
-# Build the package list.
-declare arches=()
-for dir in "${root}"/pool/*/binary-*; do
- name=$(basename "${dir}")
- arch=${name##binary-}
- arches+=("${arch}")
- repo_packages="${tmpdir}"/"${component}"/"${name}"
- mkdir -p "${repo_packages}"
- (cd "${root}" && apt-ftparchive --arch "${arch}" packages pool > "${repo_packages}"/Packages)
- (cd "${repo_packages}" && cat Packages | gzip > Packages.gz)
- (cd "${repo_packages}" && cat Packages | xz > Packages.xz)
-done
-
-# Build the release list.
-cat > "${tmpdir}"/apt.conf <<EOF
-APT {
- FTPArchive {
- Release {
- Architectures "${arches[@]}";
- Components "${component}";
- };
- };
-};
-EOF
-(cd "${tmpdir}" && apt-ftparchive -c=apt.conf release . > Release)
-rm "${tmpdir}"/apt.conf
-
-# Sign the release.
-declare -r digest_opts=("--digest-algo" "SHA512" "--cert-digest-algo" "SHA512")
-(cd "${tmpdir}" && gpg --no-default-keyring --keyring "${keyring}" --clearsign "${digest_opts[@]}" -o InRelease Release >&2)
-(cd "${tmpdir}" && gpg --no-default-keyring --keyring "${keyring}" -abs "${digest_opts[@]}" -o Release.gpg Release >&2)
-
-# Show the results.
-echo "${tmpdir}"
diff --git a/tools/nogo.js b/tools/nogo.js
deleted file mode 100644
index fc0a4d1f0..000000000
--- a/tools/nogo.js
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "checkunsafe": {
- "exclude_files": {
- "/external/": "not subject to constraint"
- }
- }
-}
diff --git a/tools/tag_release.sh b/tools/tag_release.sh
deleted file mode 100755
index f33b902d6..000000000
--- a/tools/tag_release.sh
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/bin/bash
-
-# Copyright 2019 The gVisor Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This script will optionally map a PiperOrigin-RevId to a given commit,
-# validate a provided release name, create a tag and push it. It must be
-# run manually when a release is created.
-
-set -xeu
-
-# Check arguments.
-if [ "$#" -ne 2 ]; then
- echo "usage: $0 <commit|revid> <release.rc>"
- exit 1
-fi
-
-declare -r target_commit="$1"
-declare -r release="$2"
-
-closest_commit() {
- while read line; do
- if [[ "$line" =~ "commit " ]]; then
- current_commit="${line#commit }"
- continue
- elif [[ "$line" =~ "PiperOrigin-RevId: " ]]; then
- revid="${line#PiperOrigin-RevId: }"
- [[ "${revid}" -le "$1" ]] && break
- fi
- done
- echo "${current_commit}"
-}
-
-# Is the passed identifier a sha commit?
-if ! git show "${target_commit}" &> /dev/null; then
- # Extract the commit given a piper ID.
- declare -r commit="$(git log | closest_commit "${target_commit}")"
-else
- declare -r commit="${target_commit}"
-fi
-if ! git show "${commit}" &> /dev/null; then
- echo "unknown commit: ${target_commit}"
- exit 1
-fi
-
-# Is the release name sane? Must be a date with patch/rc.
-if ! [[ "${release}" =~ ^20[0-9]{6}\.[0-9]+$ ]]; then
- declare -r expected="$(date +%Y%m%d.0)" # Use today's date.
- echo "unexpected release format: ${release}"
- echo " ... expected like ${expected}"
- exit 1
-fi
-
-# Tag the given commit (annotated, to record the committer).
-declare -r tag="release-${release}"
-(git tag -m "Release ${release}" -a "${tag}" "${commit}" && \
- git push origin tag "${tag}") || \
- (git tag -d "${tag}" && false)
diff --git a/tools/workspace_status.sh b/tools/workspace_status.sh
deleted file mode 100755
index fb09ff331..000000000
--- a/tools/workspace_status.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-
-# Copyright 2018 The gVisor Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# The STABLE_ prefix will trigger a re-link if it changes.
-echo STABLE_VERSION $(git describe --always --tags --abbrev=12 --dirty)